from django.contrib.auth import logout
from django.http import JsonResponse
from django.db import models
from rest_framework import viewsets, status, serializers
from rest_framework.decorators import api_view, permission_classes
from rest_framework.generics import CreateAPIView, GenericAPIView
from rest_framework.views import APIView
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken, AccessToken
from rest_framework_simplejwt.exceptions import TokenError
from django.utils import timezone
import logging
import os
import threading
from django.conf import settings

from .models import User, JobPosting, VideoQuestion, InterviewTemplate, JobApplication, InterviewSession, VideoAnswer, AudioAnalysis, ExpressionAnalysis, InterviewReport, VoiceProfile, SynthesizedAudio, ExpressionFrameData
from .serializers import (
    RegisterSerializer,
    LoginSerializer,
    UserRegistrationSerializer,
    UserLoginSerializer,
    TokenResponseSerializer,
    UserSerializer,
    JobPostingSerializer, 
    VideoQuestionSerializer, 
    InterviewTemplateSerializer,
    JobApplicationSerializer,
    VoiceProfileSerializer,
    SynthesizedAudioSerializer
)
from exams.models import LogistQuestion, ChoiceOption
import random
import json
from .permissions import IsHRUser, IsCandidateUser
from .services import VideoAnalysisService
from .utils.tts_utils import synthesize_text_to_audio

# 配置日志
logger = logging.getLogger(__name__)


class RegisterView(CreateAPIView):
    """用户注册视图"""
    queryset = User.objects.all()
    permission_classes = (AllowAny,)
    serializer_class = RegisterSerializer
    
    def create(self, request, *args, **kwargs):
        """创建用户，确保包含性别参数"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # 确保性别参数存在，默认为女性
        validated_data = serializer.validated_data
        if 'gender' not in validated_data:
            validated_data['gender'] = 'female'
        
        user = serializer.save()
        
        # 生成JWT token
        from rest_framework.authtoken.models import Token
        token, created = Token.objects.get_or_create(user=user)
        
        return Response({
            'token': token.key,
            'user': UserSerializer(user).data
        }, status=status.HTTP_201_CREATED)

class LoginView(GenericAPIView):
    """用户登录视图"""
    permission_classes = (AllowAny,)
    serializer_class = LoginSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # 从验证后的数据中获取用户和令牌
        validated_data = serializer.validated_data
        user = validated_data['user']
        token = validated_data['token']
        
        return Response({
            'token': token,
            'user': UserSerializer(user).data
        }, status=status.HTTP_200_OK)

class UserDetailView(APIView):
    """获取当前登录用户信息视图"""
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        serializer = UserSerializer(request.user)
        return Response(serializer.data)


class PublicJobListView(APIView):
    """候选人查看开放职位列表视图"""
    permission_classes = [IsAuthenticated, IsCandidateUser]

    def get(self, request, *args, **kwargs):
        try:
            # 获取所有开放的职位
            job_postings = JobPosting.objects.filter(
                is_active=True
            ).select_related('created_by').prefetch_related('interview_template').order_by('-created_at')
            
            jobs_data = []
            for job in job_postings:
                job_data = {
                    'id': job.id,
                    'title': job.title,
                    'description': job.description,
                    'created_at': job.created_at.isoformat(),
                    'updated_at': job.updated_at.isoformat(),
                    'created_by': job.created_by.name if job.created_by else '系统',
                    'company': job.created_by.company if job.created_by else '',
                    'interview_template': None,
                    'application_count': job.applications.count(),
                    'has_applied': False  # 用户是否已申请
                }
                
                # 检查当前用户是否已申请该职位
                if job.applications.filter(candidate=request.user).exists():
                    job_data['has_applied'] = True
                    application = job.applications.get(candidate=request.user)
                    job_data['application_status'] = application.status
                    job_data['application_score'] = application.job_fit_score
                
                # 获取面试模板信息
                if hasattr(job, 'interview_template'):
                    template = job.interview_template
                    job_data['interview_template'] = {
                        'id': template.id,
                        'title': template.title,
                        'description': template.description,
                        'logist_question_count': template.logist_questions.count(),
                        'video_question_count': template.video_questions.count(),
                        'estimated_duration': 60  # 可以根据题目数量动态计算
                    }
                
                jobs_data.append(job_data)
            
            return Response({
                'count': len(jobs_data),
                'results': jobs_data
            }, status=status.HTTP_200_OK)
            
        except Exception as e:
            return Response(
                {'error': f'获取职位列表失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class PublicJobDetailView(APIView):
    """候选人查看职位详情视图"""
    permission_classes = [IsAuthenticated, IsCandidateUser]

    def get(self, request, job_id, *args, **kwargs):
        try:
            # 获取开放的职位详情
            job = JobPosting.objects.select_related(
                'created_by'
            ).prefetch_related(
                'interview_template__logist_questions',
                'interview_template__video_questions'
            ).get(id=job_id, is_active=True)
            
            job_data = {
                'id': job.id,
                'title': job.title,
                'description': job.description,
                'created_at': job.created_at.isoformat(),
                'updated_at': job.updated_at.isoformat(),
                'created_by': job.created_by.name if job.created_by else '系统',
                'company': job.created_by.company if job.created_by else '',
                'application_count': job.applications.count(),
                'has_applied': False,
                'interview_template': None
            }
            
            # 检查当前用户是否已申请该职位
            user_application = job.applications.filter(candidate=request.user).first()
            if user_application:
                job_data['has_applied'] = True
                job_data['application_status'] = user_application.status
                job_data['application_score'] = user_application.job_fit_score
                job_data['applied_at'] = user_application.applied_at.isoformat()
            
            # 添加职位要求的匹配度
            job_data['required_match_score'] = job.required_match_score  # 数据库中已经是百分比值
            
            # 获取面试模板详细信息
            if hasattr(job, 'interview_template'):
                template = job.interview_template
                
                # 构建面试阶段信息
                stages = []
                stage_id = 1
                
                # 简历匹配阶段
                stages.append({
                    'id': stage_id,
                    'name': '简历匹配',
                    'description': '系统自动评估简历与岗位匹配度'
                })
                stage_id += 1
                
                # 逻辑测试阶段
                logist_count = template.logist_questions.count()
                if logist_count > 0:
                    stages.append({
                        'id': stage_id,
                        'name': '逻辑测试',
                        'question_count': logist_count,
                        'description': '测试逻辑思维和问题解决能力'
                    })
                    stage_id += 1
                
                # 视频面试阶段
                video_count = template.video_questions.count()
                if video_count > 0:
                    stages.append({
                        'id': stage_id,
                        'name': '视频面试',
                        'question_count': video_count,
                        'description': '评估表达能力和专业技能'
                    })
                    stage_id += 1
                
                # 报告生成阶段
                stages.append({
                    'id': stage_id,
                    'name': '面试评估',
                    'description': '生成综合评估报告'
                })
                
                job_data['interview_template'] = {
                    'id': template.id,
                    'title': template.title,
                    'description': template.description,
                    'stages': stages,
                    'total_questions': logist_count + video_count,
                    'estimated_duration': max(30, (logist_count + video_count) * 5)  # 每题预计5分钟
                }
            
            return Response(job_data, status=status.HTTP_200_OK)
            
        except JobPosting.DoesNotExist:
            return Response(
                {'error': '职位不存在或已关闭'},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {'error': f'获取职位详情失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class JobApplicationCreateView(APIView):
    """候选人上传简历申请职位视图"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def post(self, request, job_id, *args, **kwargs):
        try:
            # 检查职位是否存在且开放
            job_posting = JobPosting.objects.get(id=job_id, is_active=True)
            
            # 检查用户是否已经申请过该职位
            if JobApplication.objects.filter(candidate=request.user, job_posting=job_posting).exists():
                return Response(
                    {'error': '您已经申请过该职位'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 检查是否上传了简历文件
            if 'resume_file' not in request.FILES:
                return Response(
                    {'error': '请上传简历文件'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            resume_file = request.FILES['resume_file']
            
            # 检查文件类型
            if not resume_file.name.lower().endswith('.pdf'):
                return Response(
                    {'error': '只支持PDF格式的简历文件'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 检查文件大小（最大10MB）
            if resume_file.size > 10 * 1024 * 1024:
                return Response(
                    {'error': '简历文件大小不能超过10MB'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 使用职位设置的匹配度要求
            required_match_score = job_posting.required_match_score
            
            # 计算简历匹配度
            try:
                analysis_result = parse_resume_and_calculate_fit_score(
                    resume_file, 
                    job_posting
                )
            except Exception as e:
                return Response(
                    {'error': f'简历分析失败: {str(e)}'},
                    status=status.HTTP_500_INTERNAL_SERVER_ERROR
                )
            
            # 创建求职申请记录
            application = JobApplication.objects.create(
                candidate=request.user,
                job_posting=job_posting,
                resume_file=resume_file,
                job_fit_score=analysis_result['match_score'],
                core_skills_matched=analysis_result['core_skills_matched'],
                soft_skills_detected=analysis_result['soft_skills_detected'],
                education_summary=analysis_result['education_summary'],
                experience_summary=analysis_result['experience_summary'],
                highlights=analysis_result['highlights'],
                interview_recommendation=analysis_result['interview_recommendation'],
                screening_feedback=analysis_result['screening_feedback'],
                screening_suggestions=analysis_result['screening_suggestions']
            )
            
            # 根据匹配度自动设置初始状态
            if analysis_result['passed']:
                application.status = 'screened_pass'
                status_text = '简历筛选通过'
            else:
                application.status = 'screened_fail'
                status_text = '简历筛选未通过'
            
            application.save()
            
            # 构建返回数据
            response_data = {
                'application_id': application.id,
                'job_title': job_posting.title,
                'match_score': analysis_result['match_score'],
                'required_match_score': required_match_score,  # 数据库中已经是百分比值
                'status': application.status,
                'status_text': status_text,
                'applied_at': application.applied_at.isoformat(),
                'message': f'简历上传成功！匹配度: {analysis_result["match_score"]:.1f}% (要求: {required_match_score:.0f}%)'
            }
            
            # 如果通过，返回候选人摘要
            if analysis_result['passed']:
                response_data.update({
                    'candidate_name': request.user.name,
                    'core_skills_matched': analysis_result['core_skills_matched'],
                    'soft_skills_detected': analysis_result['soft_skills_detected'],
                    'education_summary': analysis_result['education_summary'],
                    'experience_summary': analysis_result['experience_summary'],
                    'interview_recommendation': analysis_result['interview_recommendation'],
                    'highlights': analysis_result['highlights'],
                    'resume_file_url': application.resume_file.url
                })
            else:
                # 如果未通过，返回详细反馈
                response_data.update({
                    'passed': False,
                    'final_score': analysis_result['match_score'],
                    'threshold_score': analysis_result.get('threshold_score', required_match_score),
                    'feedback': analysis_result['feedback'],
                    'suggestions': analysis_result['suggestions']
                })
            
            return Response(response_data, status=status.HTTP_201_CREATED)
            
        except JobPosting.DoesNotExist:
            return Response(
                {'error': '职位不存在或已关闭'},
                status=status.HTTP_404_NOT_FOUND
            )
        except ValueError as e:
            return Response(
                {'error': f'参数错误: {str(e)}'},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            return Response(
                {'error': f'申请失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class UserApplicationListView(APIView):
    """候选人查看自己的申请列表"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def get(self, request, *args, **kwargs):
        try:
            applications = JobApplication.objects.filter(
                candidate=request.user
            ).select_related('job_posting').order_by('-applied_at')
            
            applications_data = []
            for app in applications:
                app_data = {
                    'id': app.id,
                    'job_title': app.job_posting.title,
                    'job_id': app.job_posting.id,
                    'company': app.job_posting.created_by.company if app.job_posting.created_by else '',
                    'match_score': app.job_fit_score,
                    'required_match_score': app.job_posting.required_match_score,  # 数据库中已经是百分比值
                    'status': app.status,
                    'applied_at': app.applied_at.isoformat(),
                    'resume_file_name': app.resume_file.name.split('/')[-1] if app.resume_file else None
                }
                
                # 添加状态描述
                status_map = {
                    'pending': '待筛选',
                    'screened_pass': '简历筛选通过',
                    'screened_fail': '简历筛选未通过',
                    'interviewing': '面试中',
                    'completed': '流程已完成'
                }
                app_data['status_text'] = status_map.get(app.status, app.status)
                
                applications_data.append(app_data)
            
            return Response({
                'count': len(applications_data),
                'results': applications_data
            }, status=status.HTTP_200_OK)
            
        except Exception as e:
            return Response(
                {'error': f'获取申请列表失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class InterviewDetailView(APIView):
    """获取面试详情视图"""
    permission_classes = [IsAuthenticated, IsHRUser]

    def get(self, request, interview_id, *args, **kwargs):
        try:
            # 获取面试模板
            interview_template = InterviewTemplate.objects.select_related(
                'job_posting', 'created_by'
            ).prefetch_related(
                'logist_questions', 'video_questions'
            ).get(id=interview_id)
            
            # 获取相关的职位申请
            job_applications = JobApplication.objects.filter(
                job_posting=interview_template.job_posting
            ).select_related('candidate').prefetch_related('interview_session')
            
            # 构建面试阶段信息
            stages = []
            stage_id = 1
            
            # 简历匹配阶段
            stages.append({
                'id': stage_id,
                'name': '简历匹配',
                'question_count': 1,
                'description': '评估候选人背景与岗位匹配度'
            })
            stage_id += 1
            
            # 逻辑测试阶段
            logist_count = interview_template.logist_questions.count()
            if logist_count > 0:
                stages.append({
                    'id': stage_id,
                    'name': '逻辑测试',
                    'question_count': logist_count,
                    'description': '测试逻辑思维和问题解决能力'
                })
                stage_id += 1
            
            # 视频面试阶段
            video_count = interview_template.video_questions.count()
            if video_count > 0:
                stages.append({
                    'id': stage_id,
                    'name': '视频面试',
                    'question_count': video_count,
                    'description': '评估表达能力和专业技能'
                })
                stage_id += 1
            
            # 报告生成阶段
            stages.append({
                'id': stage_id,
                'name': '报告生成',
                'question_count': 0,
                'description': '生成综合评估报告'
            })
            
            # 构建候选人列表和统计信息
            candidates = []
            stats = {
                'candidate_count': 0,
                'completed_count': 0,
                'in_progress_count': 0,
                'pending_count': 0,
                'passed_count': 0,
                'rejected_count': 0,
                'pending_evaluation_count': 0
            }
            
            for application in job_applications:
                candidate_data = {
                    'id': application.candidate.id,
                    'name': application.candidate.name,
                    'phone': application.candidate.phone,
                    'email': application.candidate.email,
                    'avatar': application.candidate.avatar,
                    'progress': 0,
                    'current_stage': 1,
                    'overall_score': None,
                    'score_stars': 0,
                    'status': 'pending',
                    'last_activity': application.applied_at.isoformat(),
                    'last_action': '已提交申请'
                }
                
                # 计算进度和状态
                if hasattr(application, 'interview_session'):
                    session = application.interview_session
                    
                    # 根据面试会话状态计算进度
                    if session.status == 'pending':
                        candidate_data['progress'] = 10
                        candidate_data['current_stage'] = 1
                        candidate_data['status'] = 'pending'
                        candidate_data['last_action'] = '等待开始面试'
                        stats['pending_count'] += 1
                    elif session.status == 'logic_test':
                        candidate_data['progress'] = 30
                        candidate_data['current_stage'] = 2
                        candidate_data['status'] = 'in-progress'
                        candidate_data['last_action'] = '正在进行逻辑测试'
                        stats['in_progress_count'] += 1
                    elif session.status == 'video_interview':
                        candidate_data['progress'] = 60
                        candidate_data['current_stage'] = 3
                        candidate_data['status'] = 'in-progress'
                        candidate_data['last_action'] = '正在进行视频面试'
                        stats['in_progress_count'] += 1
                    elif session.status == 'generating_report':
                        candidate_data['progress'] = 90
                        candidate_data['current_stage'] = 4
                        candidate_data['status'] = 'in-progress'
                        candidate_data['last_action'] = '正在生成报告'
                        stats['pending_evaluation_count'] += 1
                    elif session.status == 'completed':
                        candidate_data['progress'] = 100
                        candidate_data['current_stage'] = 4
                        candidate_data['status'] = 'completed'
                        candidate_data['last_action'] = '面试已完成'
                        stats['completed_count'] += 1
                        
                        # 如果有报告，获取综合得分
                        if hasattr(session, 'report') and session.report.overall_score:
                            score = session.report.overall_score
                            candidate_data['overall_score'] = score
                            candidate_data['score_stars'] = min(5, max(1, round(score / 20)))
                            
                            # 判断是否通过（假设70分以上为通过）
                            if score >= 70:
                                candidate_data['status'] = 'passed'
                                stats['passed_count'] += 1
                            else:
                                candidate_data['status'] = 'rejected'
                                stats['rejected_count'] += 1
                    
                    if session.started_at:
                        candidate_data['last_activity'] = session.started_at.isoformat()
                    if session.completed_at:
                        candidate_data['last_activity'] = session.completed_at.isoformat()
                
                else:
                    # 没有面试会话，表示还在申请阶段
                    if application.status == 'pending':
                        candidate_data['status'] = 'pending'
                        candidate_data['last_action'] = '等待简历筛选'
                        stats['pending_count'] += 1
                    elif application.status == 'screened_pass':
                        candidate_data['progress'] = 20
                        candidate_data['status'] = 'pending'
                        candidate_data['last_action'] = '简历筛选通过，等待面试'
                        stats['pending_count'] += 1
                    elif application.status == 'screened_fail':
                        candidate_data['status'] = 'rejected'
                        candidate_data['last_action'] = '简历筛选未通过'
                        stats['rejected_count'] += 1
                
                candidates.append(candidate_data)
                stats['candidate_count'] += 1
            
            # 计算通过率
            pass_rate = 0
            if stats['candidate_count'] > 0:
                pass_rate = round((stats['passed_count'] / stats['candidate_count']) * 100, 1)
            
            # 构建返回数据
            response_data = {
                'id': interview_template.id,
                'title': interview_template.title,
                'position': interview_template.job_posting.title,
                'status': 'active' if interview_template.job_posting.is_active else 'inactive',
                'created_at': interview_template.job_posting.created_at.isoformat(),
                'estimated_duration': 60,  # 默认60分钟，可以根据题目数量动态计算
                'description': interview_template.description or interview_template.job_posting.description,
                'tags': ['面试', '招聘'],  # 可以根据职位类型或标签字段动态生成
                'stages': stages,
                'candidate_count': stats['candidate_count'],
                'completed_count': stats['completed_count'],
                'in_progress_count': stats['in_progress_count'],
                'pending_count': stats['pending_count'],
                'pass_rate': pass_rate,
                'passed_count': stats['passed_count'],
                'rejected_count': stats['rejected_count'],
                'pending_evaluation_count': stats['pending_evaluation_count'],
                'candidates': candidates
            }
            
            return Response(response_data, status=status.HTTP_200_OK)
            
        except InterviewTemplate.DoesNotExist:
            return Response(
                {'error': '面试模板不存在'},
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {'error': f'获取面试详情失败: {str(e)}'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


# ====================================================================
# Placeholder functions for tasks delegated to other developers
# ====================================================================

def parse_resume_and_calculate_fit_score(resume_file, job_posting):
    """
    解析简历PDF文件，提取关键词，并与职位描述进行匹配，计算岗位匹配度得分。
    :param resume_file: 上传的简历文件对象
    :param job_posting: 职位发布对象，包含所有职位信息
    :return: dict (包含详细的简历分析结果)
    """
    import os
    import tempfile
    from .resume_matcher.main import process_resume_from_job_posting
    
    # 初始化变量
    temp_file_created = False
    resume_file_path = None
    
    try:
        # 处理上传的文件：将InMemoryUploadedFile保存到临时文件
        if hasattr(resume_file, 'path') and os.path.exists(resume_file.path):
            # 如果文件已经保存到磁盘，直接使用路径
            resume_file_path = resume_file.path
            temp_file_created = False
        else:
            # 如果是内存中的文件，创建临时文件
            file_extension = os.path.splitext(resume_file.name)[1] if resume_file.name else '.pdf'
            with tempfile.NamedTemporaryFile(delete=False, suffix=file_extension) as temp_file:
                for chunk in resume_file.chunks():
                    temp_file.write(chunk)
                resume_file_path = temp_file.name
                temp_file_created = True
        
        # 调用简历匹配模块
        result = process_resume_from_job_posting(resume_file_path, job_posting)
        
        # 检查是否有错误
        if "error" in result:
            print(f"简历匹配失败: {result['error']}")
            # 返回默认结果
            return {
                'passed': False,
                'match_score': 0.0,
                'core_skills_matched': [],
                'soft_skills_detected': [],
                'education_summary': "简历解析失败",
                'experience_summary': "无法获取经验信息",
                'highlights': [],
                'interview_recommendation': 'not_recommended',
                'screening_feedback': [],
                'screening_suggestions': ["请检查简历文件格式是否正确"]
            }
        
        # 转换结果格式以匹配原有接口
        if result.get('passed', False):
            # 通过的情况
            candidate_summary = result.get('candidate_summary', {})
            return {
                'passed': True,
                'match_score': candidate_summary.get('match_score', 0.0),
                'core_skills_matched': candidate_summary.get('core_skills_matched', []),
                'soft_skills_detected': candidate_summary.get('soft_skills_detected', []),
                'education_summary': candidate_summary.get('education_summary', ''),
                'experience_summary': candidate_summary.get('experience_summary', ''),
                'highlights': candidate_summary.get('highlights', []),
                'interview_recommendation': candidate_summary.get('interview_recommendation', 'recommended'),
                'screening_feedback': [],
                'screening_suggestions': []
            }
        else:
            # 未通过的情况
            screening_result = result.get('screening_result', {})
            return {
                'passed': False,
                'match_score': screening_result.get('final_score', 0.0),
                'threshold_score': screening_result.get('threshold_score', 0.0),
                'feedback': screening_result.get('feedback', []),
                'suggestions': screening_result.get('suggestions', []),
                'core_skills_matched': [],
                'soft_skills_detected': [],
                'education_summary': "简历分析中",
                'experience_summary': "经验分析中",
                'highlights': [],
                'interview_recommendation': 'not_recommended',
                'screening_feedback': screening_result.get('feedback', []),
                'screening_suggestions': screening_result.get('suggestions', [])
            }
            
    except Exception as e:
        print(f"简历匹配过程中发生错误: {str(e)}")
        # 返回错误结果
        return {
            'passed': False,
            'match_score': 0.0,
            'core_skills_matched': [],
            'soft_skills_detected': [],
            'education_summary': "处理过程中发生错误",
            'experience_summary': "无法获取经验信息",
            'highlights': [],
            'interview_recommendation': 'not_recommended',
            'screening_feedback': [],
            'screening_suggestions': [f"处理错误: {str(e)}"]
        }
    finally:
        # 清理临时文件
        if temp_file_created and resume_file_path and os.path.exists(resume_file_path):
            try:
                os.unlink(resume_file_path)
            except Exception as e:
                print(f"清理临时文件失败: {str(e)}")

def analyze_emotion_from_video(video_url):
    """
    分析面试回答视频中的面部表情。
    :param video_url: 视频文件的URL或路径
    :return: float (表情分析得分)
    """
    try:
        # 使用新的视频分析服务
        service = VideoAnalysisService()
        result = service.sync_analyze_video(video_url, interval_seconds=3, max_concurrency=2)
        
        # 返回平均专注度分数作为表情分析得分
        return result.get('average_concentration', 0.0)
    except Exception as e:
        print(f"视频表情分析失败: {e}")
        # 返回默认分数
        return 85.0

def analyze_audio_from_video(video_url):
    """
    分析面试回答视频中的音频，使用新的音频分析算法
    :param video_url: 视频文件的URL或路径
    :return: dict (包含多维度音频分析结果的字典)
    """
    try:
        from .utils.audio_analyzer import perform_full_audio_analysis
        
        # 获取用户性别信息（这里需要根据实际情况获取）
        # 暂时使用默认值，实际应该从用户信息中获取
        gender = 'female'  # 默认使用女性
        
        # 调用新的音频分析函数
        analysis_result = perform_full_audio_analysis(video_url, gender)
        
        # 返回兼容旧接口的格式
        return {
            "clarity_score": analysis_result.get('volume_score', 85.0),
            "fluency_score": analysis_result.get('fluency_score', 90.0),
            "audio_analysis": {
                        "analysis_status": "completed",
        "transcribed_text": analysis_result.get('transcribed_text', ''),
        "word_count": analysis_result.get('word_count', 0),
        "speech_duration_seconds": analysis_result.get('speech_duration_seconds', 0.0),
        "overall_audio_score": analysis_result.get('overall_audio_score', 0.0),
        "speed_score": analysis_result.get('speed_score', 0.0),
        "pitch_score": analysis_result.get('pitch_score', 0.0),
        "volume_score": analysis_result.get('volume_score', 0.0),
        "pause_score": analysis_result.get('pause_score', 0.0),
        "fluency_score": analysis_result.get('fluency_score', 0.0)
            }
        }
    except Exception as e:
        print(f"音频分析失败: {e}")
        # 返回默认值
        return {"clarity_score": 85.0, "fluency_score": 90.0}


class JobApplicationViewSet(viewsets.ModelViewSet):
    """
    Candidate功能：职位的申请
    HR功能：查看申请列表
    """
    queryset = JobApplication.objects.all().order_by('-applied_at')
    serializer_class = JobApplicationSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        if user.role == 'hr':
            # HR可以看到所有申请，支持筛选
            queryset = JobApplication.objects.select_related(
                'candidate', 'job_posting', 'job_posting__created_by'
            ).order_by('-applied_at')
            
            # 搜索筛选
            search = self.request.query_params.get('search', None)
            if search:
                queryset = queryset.filter(
                    models.Q(candidate__name__icontains=search) |
                    models.Q(candidate__email__icontains=search) |
                    models.Q(job_posting__title__icontains=search)
                )
            
            # 状态筛选
            status = self.request.query_params.get('status', None)
            if status:
                queryset = queryset.filter(status=status)
            
            # 面试推荐筛选
            recommendation = self.request.query_params.get('recommendation', None)
            if recommendation:
                queryset = queryset.filter(interview_recommendation=recommendation)
            
            # 日期筛选
            date_from = self.request.query_params.get('date_from', None)
            if date_from:
                queryset = queryset.filter(applied_at__date__gte=date_from)
            
            date_to = self.request.query_params.get('date_to', None)
            if date_to:
                queryset = queryset.filter(applied_at__date__lte=date_to)
            
            return queryset
        elif user.role == 'candidate':
            # 候选人只能看到自己的申请
            return JobApplication.objects.filter(candidate=user).order_by('-applied_at')
        return JobApplication.objects.none()

    def perform_create(self, serializer):
        # 候选人创建申请时，自动关联自己
        if self.request.user.role != 'candidate':
            raise serializers.ValidationError("只有候选人可以申请职位。")
        
        job_posting = serializer.validated_data.get('job_posting')
        
        # 调用占位符函数计算岗位匹配度
        analysis_result = parse_resume_and_calculate_fit_score(
            serializer.validated_data.get('resume_file'),
            job_posting
        )

        serializer.save(
            candidate=self.request.user,
            job_fit_score=analysis_result['match_score'],
            core_skills_matched=analysis_result['core_skills_matched'],
            soft_skills_detected=analysis_result['soft_skills_detected'],
            education_summary=analysis_result['education_summary'],
            experience_summary=analysis_result['experience_summary'],
            highlights=analysis_result['highlights'],
            interview_recommendation=analysis_result['interview_recommendation'],
            screening_feedback=analysis_result['screening_feedback'],
            screening_suggestions=analysis_result['screening_suggestions']
        )

    def perform_destroy(self, instance):
        # 只有HR可以删除申请
        if self.request.user.role != 'hr':
            raise serializers.ValidationError("只有HR可以删除申请。")
        instance.delete()


# ====================================================================
# API ViewSets for HR Management
# ====================================================================

class JobPostingViewSet(viewsets.ModelViewSet):
    """
    HR功能：职位的增删改查
    """
    queryset = JobPosting.objects.all().order_by('-created_at')
    serializer_class = JobPostingSerializer
    permission_classes = [IsAuthenticated, IsHRUser] # 只有HR可以管理职位

    def get_queryset(self):
        # HR只能看到自己公司/自己创建的职位
        # 这里可以根据公司进行过滤，暂时先返回全部
        return JobPosting.objects.all().order_by('-created_at')

    def perform_create(self, serializer):
        # 创建时自动关联当前用户
        serializer.save(created_by=self.request.user)


class VideoQuestionViewSet(viewsets.ModelViewSet):
    """
    HR功能：视频简答题库的增删改查
    """
    queryset = VideoQuestion.objects.all().order_by('-created_at')
    serializer_class = VideoQuestionSerializer
    permission_classes = [IsAuthenticated, IsHRUser] # 只有HR可以管理题库

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)


class InterviewTemplateViewSet(viewsets.ModelViewSet):
    """
    HR功能：面试模板的增删改查
    """
    queryset = InterviewTemplate.objects.select_related(
        'job_posting', 'created_by'
    ).prefetch_related(
        'logist_questions', 'video_questions'
    ).order_by('-id')
    serializer_class = InterviewTemplateSerializer
    permission_classes = [IsAuthenticated, IsHRUser] # 只有HR可以管理模板

    def perform_create(self, serializer):
        """创建时自动设置创建者，并验证权重参数"""
        # 验证权重总和是否为1.0
        weights = [
            serializer.validated_data.get('resume_match_weight', 0.25),
            serializer.validated_data.get('professional_skill_weight', 0.20),
            serializer.validated_data.get('logical_thinking_weight', 0.15),
            serializer.validated_data.get('innovation_weight', 0.15),
            serializer.validated_data.get('stress_management_weight', 0.15),
            serializer.validated_data.get('expression_weight', 0.10),
        ]
        
        total_weight = sum(weights)
        if abs(total_weight - 1.0) > 0.001:
            raise serializers.ValidationError('六个维度的权重总和必须等于1.0')
        
        serializer.save(created_by=self.request.user)
    
    def perform_update(self, serializer):
        """更新时验证权重参数"""
        # 获取当前实例的值作为默认值
        instance = serializer.instance
        weights = [
            serializer.validated_data.get('resume_match_weight', instance.resume_match_weight),
            serializer.validated_data.get('professional_skill_weight', instance.professional_skill_weight),
            serializer.validated_data.get('logical_thinking_weight', instance.logical_thinking_weight),
            serializer.validated_data.get('innovation_weight', instance.innovation_weight),
            serializer.validated_data.get('stress_management_weight', instance.stress_management_weight),
            serializer.validated_data.get('expression_weight', instance.expression_weight),
        ]
        
        total_weight = sum(weights)
        if abs(total_weight - 1.0) > 0.001:
            raise serializers.ValidationError('六个维度的权重总和必须等于1.0')
        
        serializer.save()


@api_view(['POST'])
@permission_classes([AllowAny])
def login_view(request):
    """用户登录"""
    serializer = UserLoginSerializer(data=request.data)
    if serializer.is_valid():
        user = serializer.validated_data['user']
        access_token = AccessToken.for_user(user)
        response_data = {
            'token': str(access_token),
            'user': UserSerializer(user).data
        }
        return Response(response_data, status=status.HTTP_200_OK)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['POST'])
@permission_classes([AllowAny])
def register_view(request):
    """用户注册"""
    serializer = UserRegistrationSerializer(data=request.data)
    if serializer.is_valid():
        user = serializer.save()
        # 生成JWT token
        access_token = AccessToken.for_user(user)
        response_data = {
            'token': str(access_token),
            'user': UserSerializer(user).data
        }
        return Response(response_data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def logout_view(request):
    """用户登出"""
    try:
        # 获取refresh token
        refresh_token = request.data.get('refresh_token')
        if refresh_token:
            token = RefreshToken(refresh_token)
            token.blacklist()
        # Django logout
        logout(request)
        return Response(
            {'message': '登出成功'}, 
            status=status.HTTP_200_OK
        )
    except TokenError as e:
        return Response(
            {'error': '无效的token'}, 
            status=status.HTTP_400_BAD_REQUEST
        )
    except Exception as e:
        return Response(
            {'error': '登出失败'}, 
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def verify_token_view(request):
    """验证token有效性"""
    try:
        user = request.user
        response_data = {
            'valid': True,
            'user': UserSerializer(user).data
        }
        return Response(response_data, status=status.HTTP_200_OK)
    except Exception as e:
        return Response(
            {'valid': False, 'error': 'Token无效'}, 
            status=status.HTTP_401_UNAUTHORIZED
        )

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_profile_view(request):
    """获取用户个人资料"""
    user = request.user
    serializer = UserSerializer(user)
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(['PUT'])
@permission_classes([IsAuthenticated])
def update_profile_view(request):
    """更新用户个人资料"""
    user = request.user
    serializer = UserSerializer(user, data=request.data, partial=True)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET'])
@permission_classes([AllowAny])
def welcome_view(request):
    """API欢迎页面"""
    return Response({
        'message': '欢迎使用Django面试系统API',
        'version': '1.0.0',
        'endpoints': {
            'authentication': {
                'login': '/api/auth/login/',
                'register': '/api/auth/register/',
                'logout': '/api/auth/logout/',
                'verify_token': '/api/auth/verify/',
            },
            'user': {
                'profile': '/api/user/profile/',
                'update_profile': '/api/user/profile/update/',
            },
            'admin': '/admin/',
        },
        'test_users': {
            'hr': {
                'email': 'hr@test.com',
                'password': '123456',
                'role': 'hr'
            },
            'candidate': {
                'email': 'candidate@test.com', 
                'password': '123456',
                'role': 'candidate'
            }
        }
    }, status=status.HTTP_200_OK)


# =====================================================================
# 面试相关视图
# =====================================================================

def get_resume_info(application):
    """
    获取简历信息的占位函数
    TODO: 待同事实现简历解析功能
    """
    # 返回测试数据
    return {
        'name': application.candidate.name,
        'email': application.candidate.email,
        'phone': application.candidate.phone or '未提供',
        'skills': ['Python', 'Django', 'JavaScript', 'React'],
        'experience': '3年软件开发经验',
        'education': '计算机科学学士',
        'resume_url': application.resume_file.url if application.resume_file else None,
        'parsed_content': '这是一个测试简历内容，包含候选人的基本信息和技能描述。'
    }


def analyze_video_comprehensive(video_url, question_info, question_category):
    """
    综合视频分析函数 - 集成星火大模型API
    """
    try:
        from .utils.xinghuo_api import extract_text_from_video, analyze_interview_text
        
        # 1. 从视频中提取文本
        try:
            text_result = extract_text_from_video(video_url)
            extracted_text = text_result['text']
            text_confidence = text_result['confidence']
        except Exception as e:
            logger.error(f"文本提取失败：{str(e)}")
            extracted_text = ""
            text_confidence = 0.0
        
        # 2. AI文本分析
        ai_analysis = None
        if extracted_text:
            try:
                ai_analysis = analyze_interview_text(extracted_text, question_info)
            except Exception as e:
                logger.error(f"AI文本分析失败：{str(e)}")
                ai_analysis = {
                    'feedback': "文本分析失败",
                    'score': 75.0,
                    'keywords': [],
                    'sentiment': 'neutral'
                }
        
        # 3. 模拟音频和表情分析（待实现真实算法）
        audio_analysis = {
            'analysis_status': 'completed',
            'transcribed_text': '模拟转录文本内容',
            'word_count': random.randint(50, 200),
            'speech_duration_seconds': round(random.uniform(60, 180), 2),
            'overall_audio_score': round(random.uniform(70, 95), 2),
            'speed_score': round(random.uniform(70, 95), 2),
            'pitch_score': round(random.uniform(70, 95), 2),
            'volume_score': round(random.uniform(70, 95), 2),
            'pause_score': round(random.uniform(70, 95), 2),
            'fluency_score': round(random.uniform(70, 95), 2)
        }
        
        expression_analysis = {
            'overall_emotion_vector': {
                'confidence': round(random.uniform(0.6, 0.9), 2),
                'nervousness': round(random.uniform(0.1, 0.4), 2),
                'enthusiasm': round(random.uniform(0.5, 0.8), 2)
            },
            'average_head_angle_x': round(random.uniform(-10, 10), 2),
            'average_head_angle_y': round(random.uniform(-5, 5), 2),
            'average_eye_angle_x': round(random.uniform(-15, 15), 2)
        }
        
        # 4. 根据类别计算相应得分
        scores = {
            'expression_score': round(random.uniform(60, 95), 2),
            'innovation_score': round(random.uniform(60, 95), 2) if question_category == 'innovation' else None,
            'professional_skill_score': round(random.uniform(60, 95), 2) if question_category == 'professional' else None,
            'stress_management_score': round(random.uniform(60, 95), 2) if question_category == 'pressure' else None,
        }
        
        # 如果有AI分析结果，可以影响得分
        if ai_analysis and ai_analysis.get('score'):
            # 将AI文本分析得分融入到表达能力得分中
            scores['expression_score'] = round((scores['expression_score'] + ai_analysis['score']) / 2, 2)
        
        return {
            **scores,
            'audio_analysis': audio_analysis,
            'expression_analysis': expression_analysis,
            'text_extraction': {
                'extracted_text': extracted_text,
                'text_confidence': text_confidence
            },
            'ai_analysis': ai_analysis or {
                'feedback': "未进行AI分析",
                'score': None,
                'keywords': [],
                'sentiment': 'neutral'
            }
        }
        
    except Exception as e:
        logger.error(f"综合视频分析失败：{str(e)}")
        # 返回默认值
        return {
            'expression_score': round(random.uniform(60, 95), 2),
            'innovation_score': round(random.uniform(60, 95), 2) if question_category == 'innovation' else None,
            'professional_skill_score': round(random.uniform(60, 95), 2) if question_category == 'professional' else None,
            'stress_management_score': round(random.uniform(60, 95), 2) if question_category == 'pressure' else None,
            'audio_analysis': {
                            'analysis_status': 'completed',
            'transcribed_text': '模拟转录文本内容',
            'word_count': random.randint(50, 200),
            'speech_duration_seconds': round(random.uniform(60, 180), 2),
            'overall_audio_score': round(random.uniform(70, 95), 2),
            'speed_score': round(random.uniform(70, 95), 2),
            'pitch_score': round(random.uniform(70, 95), 2),
            'volume_score': round(random.uniform(70, 95), 2),
            'pause_score': round(random.uniform(70, 95), 2),
            'fluency_score': round(random.uniform(70, 95), 2)
            },
            'expression_analysis': {
                'overall_emotion_vector': {
                    'confidence': round(random.uniform(0.6, 0.9), 2),
                    'nervousness': round(random.uniform(0.1, 0.4), 2),
                    'enthusiasm': round(random.uniform(0.5, 0.8), 2)
                },
                'average_head_angle_x': round(random.uniform(-10, 10), 2),
                'average_head_angle_y': round(random.uniform(-5, 5), 2),
                'average_eye_angle_x': round(random.uniform(-15, 15), 2)
            },
            'text_extraction': {
                'extracted_text': "",
                'text_confidence': 0.0
            },
            'ai_analysis': {
                'feedback': "分析失败",
                'score': None,
                'keywords': [],
                'sentiment': 'neutral'
            }
        }


class InterviewResumeView(APIView):
    """获取面试简历信息"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def get(self, request, application_id):
        try:
            application = JobApplication.objects.get(
                id=application_id,
                candidate=request.user
            )
            
            resume_info = get_resume_info(application)
            
            return Response({
                'success': True,
                'data': resume_info
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'获取简历信息失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class InterviewSelfIntroductionView(APIView):
    """处理30秒自我介绍视频"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def post(self, request, application_id):
        try:
            application = JobApplication.objects.get(
                id=application_id,
                candidate=request.user
            )
            
            # 检查是否上传了视频文件
            if 'video_file' not in request.FILES:
                return Response({
                    'success': False,
                    'error': '请上传视频文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            video_file = request.FILES['video_file']
            
            # 检查文件类型
            allowed_types = ['video/mp4', 'video/webm', 'video/ogg']
            if video_file.content_type not in allowed_types:
                return Response({
                    'success': False,
                    'error': '只支持MP4、WebM、OGG格式的视频文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查文件大小（最大50MB）
            if video_file.size > 50 * 1024 * 1024:
                return Response({
                    'success': False,
                    'error': '视频文件大小不能超过50MB'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 保存文件到数据库（Django会自动处理文件保存）
            application.self_introduction_video = video_file
            application.save()
            
            return Response({
                'success': True,
                'message': '自我介绍视频上传成功',
                'data': {
                    'video_url': application.self_introduction_video.url,
                    'file_size': video_file.size,
                    'duration': None  # 可以后续添加视频时长检测
                }
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'上传视频失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class InterviewLogicQuestionsView(APIView):
    """获取逻辑思维类题目"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def get(self, request, application_id):
        try:
            application = JobApplication.objects.get(
                id=application_id,
                candidate=request.user
            )
            
            # 获取面试模板
            if not hasattr(application.job_posting, 'interview_template'):
                return Response({
                    'success': False,
                    'error': '该职位没有配置面试模板'
                }, status=status.HTTP_404_NOT_FOUND)
            
            template = application.job_posting.interview_template
            logic_questions = template.logist_questions.all()
            
            if not logic_questions.exists():
                return Response({
                    'success': True,
                    'message': '跳过该部分',
                    'data': {
                        'questions': [],
                        'total_count': 0,
                        'skip_section': True
                    }
                }, status=status.HTTP_200_OK)
            
            # 构建题目数据
            questions_data = []
            for question in logic_questions:
                question_data = {
                    'id': question.id,
                    'question_id': question.question_id,
                    'title': question.stem,  # 使用stem作为题目内容
                    'content': question.stem,  # 使用stem作为题目内容
                    'question_type': question.question_type,
                    'topic': question.topic,
                    'score': question.score,
                    'suggested_time': question.suggested_time,
                    'options': []
                }
                
                # 获取选项
                for option in question.options.all():
                    question_data['options'].append({
                        'id': option.id,
                        'text': option.content,  # 使用content字段
                        'label': option.label
                    })
                
                questions_data.append(question_data)
            
            return Response({
                'success': True,
                'data': {
                    'questions': questions_data,
                    'total_count': len(questions_data),
                    'skip_section': False
                }
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'获取逻辑题目失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class InterviewLogicAnswersView(APIView):
    """提交逻辑思维类题目答案"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def post(self, request, application_id):
        try:
            application = JobApplication.objects.get(
                id=application_id,
                candidate=request.user
            )
            
            answers = request.data.get('answers', [])
            if not answers:
                return Response({
                    'success': False,
                    'error': '答案不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取或创建面试会话
            session, created = InterviewSession.objects.get_or_create(
                application=application,
                defaults={
                    'template': application.job_posting.interview_template,
                    'status': 'logic_test'
                }
            )
            
            # 计算逻辑题得分
            total_score = 0
            correct_count = 0
            total_questions = 0
            total_possible_score = 0
            
            for answer_data in answers:
                question_id = answer_data.get('question_id')
                selected_option_id = answer_data.get('selected_option_id')
                
                try:
                    question = LogistQuestion.objects.get(id=question_id)
                    selected_option = ChoiceOption.objects.get(id=selected_option_id)
                    
                    # 累加题目总分
                    total_possible_score += question.score
                    total_questions += 1
                    
                    # 检查答案是否正确（比较选项标签与题目答案）
                    if question.answer and selected_option.label == question.answer:
                        correct_count += 1
                        total_score += question.score  # 使用题目本身的分值
                        
                except (LogistQuestion.DoesNotExist, ChoiceOption.DoesNotExist):
                    continue
            
            # 计算逻辑思维能力得分（转换为100分制）
            if total_possible_score > 0:
                # 将实际得分转换为100分制
                logical_thinking_score = (total_score / total_possible_score) * 100
            else:
                logical_thinking_score = 0
            
            # 保存逻辑思维得分
            session.logical_thinking_score = logical_thinking_score
            session.status = 'video_interview'
            session.save()
            
            return Response({
                'success': True,
                'data': {
                    'total_score': round(total_score, 2),
                    'total_possible_score': total_possible_score,
                    'logical_thinking_score': round(logical_thinking_score, 2),
                    'correct_count': correct_count,
                    'total_questions': total_questions,
                    'accuracy': round((correct_count / total_questions) * 100, 2) if total_questions > 0 else 0
                }
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'提交答案失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class InterviewVideoQuestionsView(APIView):
    """获取视频面试题目"""
    permission_classes = [IsAuthenticated]

    def get(self, request, application_id, category):
        try:
            application = JobApplication.objects.get(id=application_id)
            
            # 检查权限
            if request.user.is_candidate:
                if application.candidate != request.user:
                    return Response({'error': '无权访问此申请'}, status=status.HTTP_403_FORBIDDEN)
            elif request.user.is_hr:
                if application.job_posting.created_by != request.user:
                    return Response({'error': '无权访问此申请'}, status=status.HTTP_403_FORBIDDEN)
            
            # 获取面试会话
            try:
                session = application.interview_session
            except InterviewSession.DoesNotExist:
                return Response({'error': '面试会话不存在'}, status=status.HTTP_404_NOT_FOUND)
            
            # 获取该分类的视频题目
            video_questions = session.template.video_questions.filter(category=category)
            
            if not video_questions.exists():
                return Response({'error': f'没有找到{category}类别的视频题目'}, status=status.HTTP_404_NOT_FOUND)
            
            # 获取默认语音配置
            default_voice_profile = session.template.default_voice_profile
            
            # 为每个题目准备音频合成
            questions_with_audio = []
            for question in video_questions:
                question_data = VideoQuestionSerializer(question).data
                
                # 如果有默认语音配置，尝试合成音频
                if default_voice_profile:
                    try:
                        # 检查是否已有合成音频
                        existing_audio = SynthesizedAudio.objects.filter(
                            question=question,
                            voice_profile=default_voice_profile,
                            status='completed'
                        ).first()
                        
                        if existing_audio:
                            question_data['synthesized_audio'] = SynthesizedAudioSerializer(existing_audio).data
                        else:
                            # 异步合成音频（这里可以改为异步任务）
                            try:
                                voice_config = default_voice_profile.get_voice_config()
                                audio_path, file_size, duration = synthesize_text_to_audio(
                                    question.content, 
                                    voice_config
                                )
                                
                                # 创建音频记录
                                synthesized_audio = SynthesizedAudio.objects.create(
                                    question=question,
                                    voice_profile=default_voice_profile,
                                    text_content=question.content,
                                    audio_file=audio_path,
                                    file_size=file_size,
                                    duration=duration,
                                    status='completed'
                                )
                                
                                question_data['synthesized_audio'] = SynthesizedAudioSerializer(synthesized_audio).data
                                
                            except Exception as e:
                                logger.error(f"音频合成失败: {str(e)}")
                                question_data['synthesized_audio'] = None
                    except Exception as e:
                        logger.error(f"处理音频合成时出错: {str(e)}")
                        question_data['synthesized_audio'] = None
                else:
                    question_data['synthesized_audio'] = None
                
                questions_with_audio.append(question_data)
            
            return Response({
                'questions': questions_with_audio,
                'default_voice_profile': VoiceProfileSerializer(default_voice_profile).data if default_voice_profile else None,
                'category': category,
                'total_questions': len(questions_with_audio)
            })
            
        except JobApplication.DoesNotExist:
            return Response({'error': '申请不存在'}, status=status.HTTP_404_NOT_FOUND)


class InterviewVideoAnswersView(APIView):
    """提交视频答案并进行分析"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def post(self, request, application_id, category):
        try:
            # 添加调试信息
            print(f"DEBUG: application_id={application_id}, category={category}")
            print(f"DEBUG: request.data={request.data}")
            print(f"DEBUG: request.FILES={request.FILES}")
            
            application = JobApplication.objects.get(
                id=application_id,
                candidate=request.user
            )
            
            # 验证类别
            valid_categories = ['innovation', 'pressure', 'professional']
            if category not in valid_categories:
                return Response({
                    'success': False,
                    'error': '无效的题目类别'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取或创建面试会话
            session, created = InterviewSession.objects.get_or_create(
                application=application,
                defaults={
                    'template': application.job_posting.interview_template,
                    'status': 'video_interview'
                }
            )
            
            # 处理上传的视频文件
            processed_answers = []
            question_id = request.data.get('question_id')
            video_file = request.FILES.get('video_file')
            
            print(f"DEBUG: question_id={question_id}, video_file={video_file}")
            
            if not question_id or not video_file:
                return Response({
                    'success': False,
                    'error': '题目ID和视频文件不能为空'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                question = VideoQuestion.objects.get(id=question_id)
                print(f"DEBUG: Found question {question.id} with category {question.category}")
                
                # 检查文件类型
                allowed_types = ['video/mp4', 'video/webm', 'video/ogg']
                if video_file.content_type not in allowed_types:
                    return Response({
                        'success': False,
                        'error': '只支持MP4、WebM、OGG格式的视频文件'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 检查文件大小（最大50MB）
                if video_file.size > 50 * 1024 * 1024:
                    return Response({
                        'success': False,
                        'error': '视频文件大小不能超过50MB'
                    }, status=status.HTTP_400_BAD_REQUEST)
                
                # 创建视频答案记录（Django会自动处理文件保存）
                video_answer = VideoAnswer.objects.create(
                    session=session,
                    question=question,
                    video_url=video_file
                )
                
                print(f"DEBUG: Created video_answer {video_answer.id}")
                
                # 构建题目信息
                question_info = {
                    'title': question.title,
                    'content': question.content,
                    'category': question.category,
                    'scoring_criteria': question.scoring_criteria,
                    'excellent_answer_example': question.excellent_answer_example
                }
                
                # 调用综合视频分析函数
                analysis_result = analyze_video_comprehensive(video_answer.video_url.path, question_info, category)
                
                # 更新视频答案的分析结果
                video_answer.expression_score = analysis_result['expression_score']
                video_answer.innovation_score = analysis_result.get('innovation_score')
                video_answer.professional_skill_score = analysis_result.get('professional_skill_score')
                video_answer.stress_management_score = analysis_result.get('stress_management_score')
                
                # 保存文本提取结果
                text_extraction = analysis_result.get('text_extraction', {})
                video_answer.extracted_text = text_extraction.get('extracted_text', '')
                video_answer.text_confidence = text_extraction.get('text_confidence', 0.0)
                
                # 保存AI分析结果
                ai_analysis = analysis_result.get('ai_analysis', {})
                video_answer.ai_feedback = ai_analysis.get('feedback', '')
                video_answer.ai_score = ai_analysis.get('score')
                video_answer.ai_keywords = ai_analysis.get('keywords', [])
                video_answer.ai_sentiment = ai_analysis.get('sentiment', 'neutral')
                
                video_answer.save()
                
                # 创建音频分析记录 - 使用新的音频分析算法
                try:
                    from .utils.audio_tasks import analyze_video_audio_sync
                    
                    # 调用新的音频分析任务
                    audio_analysis_result = analyze_video_audio_sync(str(video_answer.id))
                    
                    if audio_analysis_result['status'] == 'success':
                        print(f"音频分析成功完成: {audio_analysis_result['message']}")
                    else:
                        print(f"音频分析失败: {audio_analysis_result['message']}")
                        
                except Exception as e:
                    print(f"音频分析过程中出现异常: {e}")
                    # 创建基本的音频分析记录作为备用
                    AudioAnalysis.objects.create(
                        video_answer=video_answer,
                        analysis_status='failed',
                        error_message=str(e)
                    )
                
                # 创建表情分析记录
                expression_data = analysis_result['expression_analysis']
                ExpressionAnalysis.objects.create(
                    video_answer=video_answer,
                    video_path=expression_data.get('video_path', ''),
                    interval_seconds=expression_data.get('interval_seconds', 1),
                    total_frames=expression_data.get('total_frames', 0),
                    success_frames=expression_data.get('success_frames', 0),
                    average_concentration=expression_data.get('average_concentration'),
                    max_score=expression_data.get('max_score'),
                    min_score=expression_data.get('min_score'),
                    overall_evaluation=expression_data.get('overall_evaluation'),
                    emotion_avg_score=expression_data.get('emotion_avg_score'),
                    emotion_high_ratio=expression_data.get('emotion_high_ratio'),
                    pose_avg_score=expression_data.get('pose_avg_score'),
                    pose_high_ratio=expression_data.get('pose_high_ratio'),
                    gaze_avg_score=expression_data.get('gaze_avg_score'),
                    gaze_high_ratio=expression_data.get('gaze_high_ratio'),
                    analysis_status='completed'
                )
                
                processed_answers.append({
                    'question_id': question_id,
                    'video_answer_id': video_answer.id,
                    'video_url': video_answer.video_url.url,
                    'scores': {
                        'expression_score': video_answer.expression_score,
                        'innovation_score': video_answer.innovation_score,
                        'professional_skill_score': video_answer.professional_skill_score,
                        'stress_management_score': video_answer.stress_management_score
                    }
                })
                
                print(f"DEBUG: Successfully processed answer")
                
                # 检查是否所有视频题目都已回答
                template_video_count = session.template.video_questions.count()
                answered_video_count = session.video_answers.count()
                
                print(f"DEBUG: Template video questions: {template_video_count}, Answered: {answered_video_count}")
                
                # 如果所有视频题目都已回答，更新状态为generating_report
                if answered_video_count >= template_video_count:
                    session.status = 'generating_report'
                    session.completed_at = timezone.now()
                    session.save()
                    print(f"DEBUG: Interview session updated to generating_report status")
                    
                    # 同时更新申请状态为completed
                    application.status = 'completed'
                    application.save()
                    print(f"DEBUG: Application status updated to completed")
                
            except VideoQuestion.DoesNotExist:
                print(f"DEBUG: Question {question_id} not found")
                return Response({
                    'success': False,
                    'error': '题目不存在'
                }, status=status.HTTP_404_NOT_FOUND)
            
            return Response({
                'success': True,
                'data': {
                    'processed_answers': processed_answers,
                    'category': category,
                    'message': f'{category}类题目答案提交成功'
                }
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            print(f"DEBUG: Exception occurred: {str(e)}")
            return Response({
                'success': False,
                'error': f'提交视频答案失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class InterviewResultsView(APIView):
    """查询面试所有分数结果"""
    permission_classes = [IsAuthenticated]
    
    def get(self, request, application_id):
        try:
            # 根据用户角色获取申请
            if request.user.is_hr:
                application = JobApplication.objects.get(id=application_id)
            else:
                application = JobApplication.objects.get(
                    id=application_id,
                    candidate=request.user
                )
            
            # 获取面试会话
            if not hasattr(application, 'interview_session'):
                return Response({
                    'success': False,
                    'error': '该申请还没有面试会话'
                }, status=status.HTTP_404_NOT_FOUND)
            
            session = application.interview_session
            
            # 检查面试是否已完成（被锁定）
            is_locked = session.status in ['generating_report', 'completed']
            
            # 构建基础结果数据
            result_data = {
                'application_info': {
                    'id': application.id,
                    'candidate_name': application.candidate.name,
                    'candidate_email': application.candidate.email,
                    'job_title': application.job_posting.title,
                    'applied_at': application.applied_at.isoformat(),
                    'status': application.status
                },
                'session_info': {
                    'id': session.id,
                    'status': session.status,
                    'started_at': session.started_at.isoformat() if session.started_at else None,
                    'completed_at': session.completed_at.isoformat() if session.completed_at else None,
                    'is_locked': is_locked
                },
                'self_introduction_video': application.self_introduction_video.url if application.self_introduction_video else None
            }
            
            # 根据用户角色返回不同数据
            if request.user.is_hr:
                # HR视角：显示所有详细信息
                result_data['scores'] = {
                    'logical_thinking_score': session.logical_thinking_score,
                    'video_scores': []
                }
                
                # 获取视频答案得分
                video_answers = session.video_answers.all().select_related('question')
                for video_answer in video_answers:
                    video_score_data = {
                        'question_id': video_answer.question.id,
                        'question_title': video_answer.question.title,
                        'question_category': video_answer.question.category,
                        'question_category_display': video_answer.question.get_category_display(),
                        'video_url': video_answer.video_url.url,
                        'scores': {
                            'expression_score': video_answer.expression_score,
                            'innovation_score': video_answer.innovation_score,
                            'professional_skill_score': video_answer.professional_skill_score,
                            'stress_management_score': video_answer.stress_management_score
                        },
                        'answered_at': video_answer.answered_at.isoformat()
                    }
                    
                    # 添加音频分析结果 - 使用新的音频分析数据
                    if hasattr(video_answer, 'audio_analysis'):
                        audio = video_answer.audio_analysis
                        
                        video_score_data['audio_analysis'] = {
                            'analysis_status': audio.analysis_status,
                            'overall_audio_score': audio.overall_audio_score,
                            'speed_score': audio.speed_score,
                            'pitch_score': audio.pitch_score,
                            'volume_score': audio.volume_score,
                            'pause_score': audio.pause_score,
                            'fluency_score': audio.fluency_score,
                            'transcribed_text': audio.transcribed_text,
                            'word_count': audio.word_count,
                            'speech_duration_seconds': audio.speech_duration_seconds,
                            'speech_rate_syllables_per_second': audio.speech_rate_syllables_per_second,
                            'average_pitch_frequency_hz': audio.average_pitch_frequency_hz,
                            'average_volume_db': audio.average_volume_db,
                            'total_pause_frequency_per_second': audio.total_pause_frequency_per_second,
                            'articulation_rate_syllables_per_second': audio.articulation_rate_syllables_per_second,
                            'correction_count_per_second': audio.correction_count_per_second,
                            'f2_slope_hz_per_ms': audio.f2_slope_hz_per_ms,
                            'articulation_rate_score': audio.articulation_rate_score,
                            'correction_count_score': audio.correction_count_score,
                            'f2_slope_score': audio.f2_slope_score,
                            'error_message': audio.error_message if audio.analysis_status == 'failed' else None
                        }
                        
                        # 添加帧数据（用于前端实时显示）
                        if audio.analysis_status == 'completed':
                            frame_data = []
                            for frame in audio.frame_data.all().order_by('timestamp'):
                                frame_data.append({
                                    'timestamp_seconds': frame.timestamp,
                                    'pitch': frame.pitch,
                                    'volume': frame.volume,
                                    'pitch_score_per_second': frame.pitch_score_per_second,
                                    'volume_score_per_second': frame.volume_score_per_second
                                })
                            video_score_data['audio_analysis']['frame_data'] = frame_data
                    
                    # 添加表情分析结果
                    if hasattr(video_answer, 'expression_analysis'):
                        expression = video_answer.expression_analysis
                        video_score_data['expression_analysis'] = {
                            'average_concentration': expression.average_concentration,
                            'emotion_avg_score': expression.emotion_avg_score,
                            'pose_avg_score': expression.pose_avg_score,
                            'gaze_avg_score': expression.gaze_avg_score,
                            'overall_evaluation': expression.overall_evaluation,
                            'total_frames': expression.total_frames,
                            'success_frames': expression.success_frames
                        }
                    
                    result_data['scores']['video_scores'].append(video_score_data)
                
                # 计算六个维度加权总分
                template = session.template
                weighted_score = 0.0
                total_weight = 0.0
                
                # 简历匹配度得分
                if application.job_fit_score:
                    weighted_score += application.job_fit_score * template.resume_match_weight
                    total_weight += template.resume_match_weight
                
                # 逻辑思维能力得分
                if session.logical_thinking_score:
                    weighted_score += session.logical_thinking_score * template.logical_thinking_weight
                    total_weight += template.logical_thinking_weight
                
                # 计算各维度平均分
                expression_scores = [va.expression_score for va in video_answers if va.expression_score]
                innovation_scores = [va.innovation_score for va in video_answers if va.innovation_score]
                professional_scores = [va.professional_skill_score for va in video_answers if va.professional_skill_score]
                stress_scores = [va.stress_management_score for va in video_answers if va.stress_management_score]
                
                expression_avg_score = sum(expression_scores) / len(expression_scores) if expression_scores else None
                innovation_avg_score = sum(innovation_scores) / len(innovation_scores) if innovation_scores else None
                professional_avg_score = sum(professional_scores) / len(professional_scores) if professional_scores else None
                stress_avg_score = sum(stress_scores) / len(stress_scores) if stress_scores else None
                
                # 专业技能平均分
                if professional_avg_score:
                    weighted_score += professional_avg_score * template.professional_skill_weight
                    total_weight += template.professional_skill_weight
                
                # 创新能力平均分
                if innovation_avg_score:
                    weighted_score += innovation_avg_score * template.innovation_weight
                    total_weight += template.innovation_weight
                
                # 压力应对平均分
                if stress_avg_score:
                    weighted_score += stress_avg_score * template.stress_management_weight
                    total_weight += template.stress_management_weight
                
                # 表达能力平均分
                if expression_avg_score:
                    weighted_score += expression_avg_score * template.expression_weight
                    total_weight += template.expression_weight
                
                # 计算最终加权总分
                result_data['scores']['overall_score'] = round(weighted_score / total_weight, 2) if total_weight > 0 else 0
                
            else:
                # 候选人视角：只显示基本信息，不显示详细分数
                result_data['progress'] = {
                    'logical_thinking_score': session.logical_thinking_score,
                    'total_video_questions': session.template.video_questions.count(),
                    'answered_video_questions': session.video_answers.count(),
                    'percentage': round((session.video_answers.count() / session.template.video_questions.count()) * 100) if session.template.video_questions.count() > 0 else 0
                }
                
                # 如果面试已完成，显示基本信息
                if is_locked:
                    result_data['message'] = '面试已完成，等待生成报告'
                else:
                    result_data['message'] = '面试进行中'
            
            return Response({
                'success': True,
                'data': result_data
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'获取面试结果失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class HRInterviewManagementView(APIView):
    """HR面试管理视图 - 查看所有面试状态和视频"""
    permission_classes = [IsAuthenticated, IsHRUser]
    
    def get(self, request, application_id):
        try:
            # HR可以查看任何申请
            application = JobApplication.objects.get(id=application_id)
            
            # 获取面试会话
            if not hasattr(application, 'interview_session'):
                return Response({
                    'success': False,
                    'error': '该申请还没有面试会话'
                }, status=status.HTTP_404_NOT_FOUND)
            
            session = application.interview_session
            
            # 构建HR视角的数据
            hr_data = {
                'application_info': {
                    'id': application.id,
                    'candidate_name': application.candidate.name,
                    'candidate_email': application.candidate.email,
                    'candidate_phone': application.candidate.phone,
                    'job_title': application.job_posting.title,
                    'applied_at': application.applied_at.isoformat(),
                    'status': application.status,
                    'job_fit_score': application.job_fit_score,
                    'self_introduction_video': application.self_introduction_video.url if application.self_introduction_video else None
                },
                'session_info': {
                    'id': session.id,
                    'status': session.status,
                    'started_at': session.started_at.isoformat() if session.started_at else None,
                    'completed_at': session.completed_at.isoformat() if session.completed_at else None,
                    'template_title': session.template.title,
                    'template_description': session.template.description
                },
                'interview_progress': {
                    'logical_thinking_score': session.logical_thinking_score,
                    'total_video_questions': session.template.video_questions.count(),
                    'answered_video_questions': session.video_answers.count(),
                    'is_completed': session.status in ['generating_report', 'completed']
                },
                'video_answers': []
            }
            
            # 获取所有视频答案的详细信息
            video_answers = session.video_answers.all().select_related('question').prefetch_related('audio_analysis', 'expression_analysis')
            
            for video_answer in video_answers:
                video_data = {
                    'id': video_answer.id,
                    'question': {
                        'id': video_answer.question.id,
                        'title': video_answer.question.title,
                        'content': video_answer.question.content,
                        'category': video_answer.question.category,
                        'category_display': video_answer.question.get_category_display(),
                        'answer_duration': video_answer.question.answer_duration,
                        'excellent_answer_example': video_answer.question.excellent_answer_example,
                        'scoring_criteria': video_answer.question.scoring_criteria
                    },
                    'video_url': video_answer.video_url.url,
                    'answered_at': video_answer.answered_at.isoformat(),
                    'scores': {
                        'expression_score': video_answer.expression_score,
                        'innovation_score': video_answer.innovation_score,
                        'professional_skill_score': video_answer.professional_skill_score,
                        'stress_management_score': video_answer.stress_management_score
                    }
                }
                
                # 添加音频分析结果
                if hasattr(video_answer, 'audio_analysis'):
                    audio = video_answer.audio_analysis
                    video_data['audio_analysis'] = {
                        'analysis_status': audio.analysis_status,
                        'transcribed_text': audio.transcribed_text,
                        'word_count': audio.word_count,
                        'speech_duration_seconds': audio.speech_duration_seconds,
                        'overall_audio_score': audio.overall_audio_score,
                        'speed_score': audio.speed_score,
                        'pitch_score': audio.pitch_score,
                        'volume_score': audio.volume_score,
                        'pause_score': audio.pause_score,
                        'fluency_score': audio.fluency_score,
                        'gender': audio.gender,
                        'speech_rate_syllables_per_second': audio.speech_rate_syllables_per_second,
                        'average_pitch_frequency_hz': audio.average_pitch_frequency_hz,
                        'average_volume_db': audio.average_volume_db,
                        'total_pause_frequency_per_second': audio.total_pause_frequency_per_second,
                        'articulation_rate_syllables_per_second': audio.articulation_rate_syllables_per_second,
                        'articulation_rate_score': audio.articulation_rate_score,
                        'correction_count_per_second': audio.correction_count_per_second,
                        'correction_count_score': audio.correction_count_score,
                        'f2_slope_hz_per_ms': audio.f2_slope_hz_per_ms,
                        'f2_slope_score': audio.f2_slope_score,
                        'created_at': audio.created_at.isoformat() if audio.created_at else None
                    }
                
                # 添加表情分析结果
                if hasattr(video_answer, 'expression_analysis'):
                    expression = video_answer.expression_analysis
                    video_data['expression_analysis'] = {
                        'average_concentration': expression.average_concentration,
                        'emotion_avg_score': expression.emotion_avg_score,
                        'pose_avg_score': expression.pose_avg_score,
                        'gaze_avg_score': expression.gaze_avg_score,
                        'overall_evaluation': expression.overall_evaluation,
                        'total_frames': expression.total_frames,
                        'success_frames': expression.success_frames,
                        'analyzed_at': expression.analyzed_at.isoformat() if expression.analyzed_at else None
                    }
                
                hr_data['video_answers'].append(video_data)
            
            # 计算六个维度加权总分
            template = session.template
            weighted_score = 0.0
            total_weight = 0.0
            
            # 简历匹配度得分
            if application.job_fit_score:
                weighted_score += application.job_fit_score * template.resume_match_weight
                total_weight += template.resume_match_weight
            
            # 逻辑思维能力得分
            if session.logical_thinking_score:
                weighted_score += session.logical_thinking_score * template.logical_thinking_weight
                total_weight += template.logical_thinking_weight
            
            # 计算各维度平均分
            expression_scores = [va.expression_score for va in video_answers if va.expression_score]
            innovation_scores = [va.innovation_score for va in video_answers if va.innovation_score]
            professional_scores = [va.professional_skill_score for va in video_answers if va.professional_skill_score]
            stress_scores = [va.stress_management_score for va in video_answers if va.stress_management_score]
            
            expression_avg_score = sum(expression_scores) / len(expression_scores) if expression_scores else None
            innovation_avg_score = sum(innovation_scores) / len(innovation_scores) if innovation_scores else None
            professional_avg_score = sum(professional_scores) / len(professional_scores) if professional_scores else None
            stress_avg_score = sum(stress_scores) / len(stress_scores) if stress_scores else None
            
            # 专业技能平均分
            if professional_avg_score:
                weighted_score += professional_avg_score * template.professional_skill_weight
                total_weight += template.professional_skill_weight
            
            # 创新能力平均分
            if innovation_avg_score:
                weighted_score += innovation_avg_score * template.innovation_weight
                total_weight += template.innovation_weight
            
            # 压力应对平均分
            if stress_avg_score:
                weighted_score += stress_avg_score * template.stress_management_weight
                total_weight += template.stress_management_weight
            
            # 表达能力平均分
            if expression_avg_score:
                weighted_score += expression_avg_score * template.expression_weight
                total_weight += template.expression_weight
            
            # 计算最终加权总分
            hr_data['overall_score'] = round(weighted_score / total_weight, 2) if total_weight > 0 else 0
            
            return Response({
                'success': True,
                'data': hr_data
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'获取面试管理数据失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class InterviewStatusCheckView(APIView):
    """面试状态检查接口 - 用于前端检查面试是否完成"""
    permission_classes = [IsAuthenticated, IsCandidateUser]
    
    def get(self, request, application_id):
        try:
            application = JobApplication.objects.get(
                id=application_id,
                candidate=request.user
            )
            
            if not hasattr(application, 'interview_session'):
                return Response({
                    'success': True,
                    'data': {
                        'has_session': False,
                        'status': 'no_session',
                        'message': '还没有开始面试'
                    }
                }, status=status.HTTP_200_OK)
            
            session = application.interview_session
            
            # 检查面试是否已完成（被锁定）
            is_locked = session.status in ['generating_report', 'completed']
            
            # 计算进度
            total_video_questions = session.template.video_questions.count()
            answered_video_questions = session.video_answers.count()
            progress_percentage = round((answered_video_questions / total_video_questions) * 100) if total_video_questions > 0 else 0
            
            return Response({
                'success': True,
                'data': {
                    'has_session': True,
                    'status': session.status,
                    'is_locked': is_locked,
                    'progress': {
                        'total_video_questions': total_video_questions,
                        'answered_video_questions': answered_video_questions,
                        'percentage': progress_percentage
                    },
                    'scores': {
                        'logical_thinking_score': session.logical_thinking_score,
                        'overall_score': None  # 候选人视角不显示综合得分
                    },
                    'message': '面试已完成，等待生成报告' if is_locked else '面试进行中'
                }
            }, status=status.HTTP_200_OK)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'检查面试状态失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class JobApplicationStatisticsView(APIView):
    """HR申请统计接口"""
    permission_classes = [IsAuthenticated, IsHRUser]
    
    def get(self, request):
        try:
            # 获取基础查询集
            queryset = JobApplication.objects.all()
            
            # 应用筛选条件（与列表API保持一致）
            search = request.query_params.get('search', None)
            if search:
                queryset = queryset.filter(
                    models.Q(candidate__name__icontains=search) |
                    models.Q(candidate__email__icontains=search) |
                    models.Q(job_posting__title__icontains=search)
                )
            
            status = request.query_params.get('status', None)
            if status:
                queryset = queryset.filter(status=status)
            
            recommendation = request.query_params.get('recommendation', None)
            if recommendation:
                queryset = queryset.filter(interview_recommendation=recommendation)
            
            date_from = request.query_params.get('date_from', None)
            if date_from:
                queryset = queryset.filter(applied_at__date__gte=date_from)
            
            date_to = request.query_params.get('date_to', None)
            if date_to:
                queryset = queryset.filter(applied_at__date__lte=date_to)
            
            # 计算统计数据
            total_applications = queryset.count()
            pending_applications = queryset.filter(status='pending').count()
            passed_applications = queryset.filter(status='screened_pass').count()
            failed_applications = queryset.filter(status='screened_fail').count()
            interviewing_applications = queryset.filter(status='interviewing').count()
            completed_applications = queryset.filter(status='completed').count()
            
            # 按推荐状态统计
            recommended_applications = queryset.filter(interview_recommendation='recommended').count()
            conditional_applications = queryset.filter(interview_recommendation='conditional').count()
            not_recommended_applications = queryset.filter(interview_recommendation='not_recommended').count()
            
            statistics = {
                'total_applications': total_applications,
                'pending_applications': pending_applications,
                'passed_applications': passed_applications,
                'failed_applications': failed_applications,
                'interviewing_applications': interviewing_applications,
                'completed_applications': completed_applications,
                'recommended_applications': recommended_applications,
                'conditional_applications': conditional_applications,
                'not_recommended_applications': not_recommended_applications
            }
            
            return Response({
                'success': True,
                'data': statistics
            }, status=status.HTTP_200_OK)
            
        except Exception as e:
            return Response({
                'success': False,
                'error': f'获取统计数据失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class GenerateInterviewReportView(APIView):
    """生成面试综合报告"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request, application_id):
        try:
            # 根据用户角色获取申请
            if request.user.is_hr:
                application = JobApplication.objects.get(id=application_id)
            else:
                application = JobApplication.objects.get(
                    id=application_id,
                    candidate=request.user
                )
            
            # 检查是否有面试会话
            if not hasattr(application, 'interview_session'):
                return Response({
                    'success': False,
                    'error': '该申请还没有面试会话'
                }, status=status.HTTP_404_NOT_FOUND)
            
            session = application.interview_session
            
            # 检查面试是否已完成
            if session.status not in ['generating_report', 'completed']:
                return Response({
                    'success': False,
                    'error': '面试尚未完成，无法生成报告'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 检查是否已有报告
            if hasattr(session, 'report'):
                return Response({
                    'success': False,
                    'error': '报告已存在',
                    'report_id': session.report.id
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 收集面试数据
            session_data = self.collect_session_data(session)
            
            # 生成AI综合评语
            try:
                from .utils.xinghuo_api import generate_interview_report
                ai_summary = generate_interview_report(session_data)
            except Exception as e:
                logger.error(f"生成AI报告失败：{str(e)}")
                ai_summary = "AI报告生成失败，请手动评估。"
            
            # 计算各维度平均分
            video_answers = session.video_answers.all()
            expression_scores = [va.expression_score for va in video_answers if va.expression_score]
            innovation_scores = [va.innovation_score for va in video_answers if va.innovation_score]
            professional_scores = [va.professional_skill_score for va in video_answers if va.professional_skill_score]
            stress_scores = [va.stress_management_score for va in video_answers if va.stress_management_score]
            
            # 计算六个维度加权总分
            template = session.template
            weighted_score = 0.0
            total_weight = 0.0
            
            # 简历匹配度得分
            if application.job_fit_score:
                weighted_score += application.job_fit_score * template.resume_match_weight
                total_weight += template.resume_match_weight
            
            # 逻辑思维能力得分
            if session.logical_thinking_score:
                weighted_score += session.logical_thinking_score * template.logical_thinking_weight
                total_weight += template.logical_thinking_weight
            
            # 计算各维度平均分
            expression_avg_score = sum(expression_scores) / len(expression_scores) if expression_scores else None
            innovation_avg_score = sum(innovation_scores) / len(innovation_scores) if innovation_scores else None
            professional_avg_score = sum(professional_scores) / len(professional_scores) if professional_scores else None
            stress_avg_score = sum(stress_scores) / len(stress_scores) if stress_scores else None
            
            # 专业技能平均分
            if professional_avg_score:
                weighted_score += professional_avg_score * template.professional_skill_weight
                total_weight += template.professional_skill_weight
            
            # 创新能力平均分
            if innovation_avg_score:
                weighted_score += innovation_avg_score * template.innovation_weight
                total_weight += template.innovation_weight
            
            # 压力应对平均分
            if stress_avg_score:
                weighted_score += stress_avg_score * template.stress_management_weight
                total_weight += template.stress_management_weight
            
            # 表达能力平均分（将在后面计算）
            expression_analysis_score = None
            audio_analysis_score = None
            
            # 计算综合表达能力得分（面部表情分析 + 音频分析的平均分）
            # 获取表情分析得分
            if session_data.get('expression_analysis_summary'):
                # 从表情分析汇总中获取平均专注度分数
                expression_scores_list = []
                for question_key, analysis_data in session_data['expression_analysis_summary'].items():
                    if 'average_concentration' in analysis_data:
                        expression_scores_list.append(analysis_data['average_concentration'])
                if expression_scores_list:
                    expression_analysis_score = sum(expression_scores_list) / len(expression_scores_list)
            
            # 获取音频分析得分
            if session_data.get('audio_analysis_summary'):
                # 从音频分析汇总中计算平均分
                audio_scores_list = []
                for question_key, analysis_data in session_data['audio_analysis_summary'].items():
                    # 使用音频综合得分
                    overall_audio_score = analysis_data.get('overall_audio_score', 0)
                    if overall_audio_score:
                        audio_scores_list.append(overall_audio_score)
                if audio_scores_list:
                    audio_analysis_score = sum(audio_scores_list) / len(audio_scores_list)
            
            # 计算综合表达能力得分（表情分析50% + 音频分析50%）
            if expression_analysis_score is not None and audio_analysis_score is not None:
                expression_avg_score = (expression_analysis_score * 0.5 + audio_analysis_score * 0.5)
            elif expression_analysis_score is not None:
                expression_avg_score = expression_analysis_score
            elif audio_analysis_score is not None:
                expression_avg_score = audio_analysis_score
            else:
                # 如果没有表情和音频分析，使用原有的expression_scores
                expression_avg_score = sum(expression_scores) / len(expression_scores) if expression_scores else None
            
            # 将表达能力得分加入加权总分计算
            if expression_avg_score:
                weighted_score += expression_avg_score * template.expression_weight
                total_weight += template.expression_weight
            
            # 计算最终加权总分
            overall_score = weighted_score / total_weight if total_weight > 0 else 0
            
            # 创建报告
            report = InterviewReport.objects.create(
                session=session,
                overall_score=round(overall_score, 2),
                summary=ai_summary,
                resume_match_score=application.job_fit_score,
                logical_thinking_score=session.logical_thinking_score,
                expression_avg_score=expression_avg_score,
                innovation_avg_score=innovation_avg_score,
                professional_avg_score=professional_avg_score,
                stress_management_avg_score=stress_avg_score,
                audio_analysis_summary=session_data.get('audio_analysis_summary', {}),
                expression_analysis_summary=session_data.get('expression_analysis_summary', {}),
                text_analysis_summary=session_data.get('text_analysis_summary', {}),
                final_decision='pending'
            )
            
            # 更新最终决策
            report.update_final_decision()
            
            # 更新会话状态
            session.status = 'completed'
            session.save()
            
            return Response({
                'success': True,
                'message': '综合报告生成成功',
                'data': {
                    'report_id': report.id,
                    'overall_score': report.overall_score,
                    'summary': report.summary,
                    'generated_at': report.generated_at.isoformat()
                }
            }, status=status.HTTP_201_CREATED)
            
        except JobApplication.DoesNotExist:
            return Response({
                'success': False,
                'error': '申请不存在或无权限访问'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            logger.error(f"生成报告失败: {str(e)}")
            import traceback
            logger.error(f"详细错误信息: {traceback.format_exc()}")
            return Response({
                'success': False,
                'error': f'生成报告失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def collect_session_data(self, session):
        """收集面试会话数据"""
        application = session.application
        
        # 收集视频答案数据
        video_answers = session.video_answers.all()
        text_analysis_summary = {}
        audio_analysis_summary = {}
        expression_analysis_summary = {}
        
        for va in video_answers:
            question_key = f"question_{va.question.id}"
            
            # 文本分析汇总
            if va.extracted_text:
                text_analysis_summary[question_key] = {
                    'extracted_text': va.extracted_text,
                    'text_confidence': va.text_confidence,
                    'ai_feedback': va.ai_feedback,
                    'ai_score': va.ai_score,
                    'ai_keywords': va.ai_keywords,
                    'ai_sentiment': va.ai_sentiment
                }
            
            # 音频分析汇总 - 使用新的音频分析数据
            if hasattr(va, 'audio_analysis'):
                audio = va.audio_analysis
                audio_analysis_summary[question_key] = {
                    'analysis_status': audio.analysis_status,
                    'overall_audio_score': audio.overall_audio_score,
                    'speed_score': audio.speed_score,
                    'pitch_score': audio.pitch_score,
                    'volume_score': audio.volume_score,
                    'pause_score': audio.pause_score,
                    'fluency_score': audio.fluency_score,
                    'transcribed_text': audio.transcribed_text,
                    'word_count': audio.word_count,
                    'speech_duration_seconds': audio.speech_duration_seconds,
                    'speech_rate_syllables_per_second': audio.speech_rate_syllables_per_second,
                    'average_pitch_frequency_hz': audio.average_pitch_frequency_hz,
                    'average_volume_db': audio.average_volume_db,
                    'total_pause_frequency_per_second': audio.total_pause_frequency_per_second,
                    'articulation_rate_syllables_per_second': audio.articulation_rate_syllables_per_second,
                    'correction_count_per_second': audio.correction_count_per_second,
                    'f2_slope_hz_per_ms': audio.f2_slope_hz_per_ms,
                    'articulation_rate_score': audio.articulation_rate_score,
                    'correction_count_score': audio.correction_count_score,
                    'f2_slope_score': audio.f2_slope_score,
                    'error_message': audio.error_message if audio.analysis_status == 'failed' else None
                }
            
            # 表情分析汇总
            if hasattr(va, 'expression_analysis'):
                expression = va.expression_analysis
                expression_analysis_summary[question_key] = {
                    'average_concentration': expression.average_concentration,
                    'emotion_avg_score': expression.emotion_avg_score,
                    'pose_avg_score': expression.pose_avg_score,
                    'gaze_avg_score': expression.gaze_avg_score,
                    'overall_evaluation': expression.overall_evaluation,
                    'total_frames': expression.total_frames,
                    'success_frames': expression.success_frames
                }
        
        return {
            'candidate_name': application.candidate.name,
            'job_title': application.job_posting.title,
            'resume_match_score': application.job_fit_score,
            'core_skills_matched': application.core_skills_matched,
            'soft_skills_detected': application.soft_skills_detected,
            'logical_thinking_score': session.logical_thinking_score,
            'expression_avg_score': session.video_answers.aggregate(
                avg=models.Avg('expression_score')
            )['avg'] or None,
            'innovation_avg_score': session.video_answers.aggregate(
                avg=models.Avg('innovation_score')
            )['avg'] or None,
            'professional_avg_score': session.video_answers.aggregate(
                avg=models.Avg('professional_skill_score')
            )['avg'] or None,
            'stress_management_avg_score': session.video_answers.aggregate(
                avg=models.Avg('stress_management_score')
            )['avg'] or None,
            'audio_analysis_summary': audio_analysis_summary,
            'expression_analysis_summary': expression_analysis_summary,
            'text_analysis_summary': text_analysis_summary
        }


class HRReportReviewView(APIView):
    """HR报告审核和评论"""
    permission_classes = [IsAuthenticated, IsHRUser]
    
    def get(self, request, report_id):
        """获取报告详情"""
        try:
            report = InterviewReport.objects.select_related(
                'session__application__candidate',
                'session__application__job_posting'
            ).prefetch_related(
                'session__video_answers__question',
                'session__video_answers__audio_analysis',
                'session__video_answers__expression_analysis'
            ).get(id=report_id)
            
            application = report.session.application
            session = report.session
            
            # 1. 基础信息
            report_data = {
                'id': report.id,
                'candidate_info': {
                    'name': application.candidate.name,
                    'email': application.candidate.email,
                    'phone': application.candidate.phone,
                    'job_title': application.job_posting.title,
                    'applied_at': application.applied_at.isoformat()
                },
                'scores': {
                    'overall_score': report.overall_score,
                    'resume_match_score': report.resume_match_score,
                    'logical_thinking_score': report.logical_thinking_score,
                    'expression_avg_score': report.expression_avg_score,
                    'innovation_avg_score': report.innovation_avg_score,
                    'professional_avg_score': report.professional_avg_score,
                    'stress_management_avg_score': report.stress_management_avg_score
                },
                'ai_summary': report.summary,
                'hr_review': {
                    'hr_comments': report.hr_comments,
                    'hr_rating': report.hr_rating,
                    'hr_recommendation': report.hr_recommendation,
                    'hr_reviewed_at': report.hr_reviewed_at.isoformat() if report.hr_reviewed_at else None
                },
                'final_decision': report.final_decision,
                'decision_reason': report.decision_reason,
                'generated_at': report.generated_at.isoformat(),
                'updated_at': report.updated_at.isoformat()
            }
            
            # 2. 详细的简历分析结果
            report_data['resume_analysis'] = {
                'job_fit_score': application.job_fit_score,
                'core_skills_matched': application.core_skills_matched,
                'soft_skills_detected': application.soft_skills_detected,
                'education_summary': application.education_summary,
                'experience_summary': application.experience_summary,
                'highlights': application.highlights,
                'interview_recommendation': application.interview_recommendation,
                'screening_feedback': application.screening_feedback,
                'screening_suggestions': application.screening_suggestions,
                'resume_file_url': application.resume_file.url if application.resume_file and hasattr(application.resume_file, 'url') else None,
                'self_introduction_video_url': application.self_introduction_video.url if application.self_introduction_video and hasattr(application.self_introduction_video, 'url') else None
            }
            
            # 3. 各个题目的详细回答和分值
            video_answers_detail = []
            for video_answer in session.video_answers.all():
                question_detail = {
                    'question_info': {
                        'id': video_answer.question.id,
                        'title': video_answer.question.title,
                        'content': video_answer.question.content,
                        'category': video_answer.question.category,
                        'category_display': video_answer.question.get_category_display(),
                        'answer_duration': video_answer.question.answer_duration,
                        'excellent_answer_example': video_answer.question.excellent_answer_example,
                        'scoring_criteria': video_answer.question.scoring_criteria,
                        'topic_tags': video_answer.question.topic_tags
                    },
                    'answer_info': {
                        'id': video_answer.id,
                        'video_url': video_answer.video_url.url if video_answer.video_url and hasattr(video_answer.video_url, 'url') else None,
                        'answered_at': video_answer.answered_at.isoformat() if video_answer.answered_at else None,
                        'extracted_text': video_answer.extracted_text,
                        'text_confidence': video_answer.text_confidence
                    },
                    'scores': {
                        'expression_score': video_answer.expression_score,
                        'innovation_score': video_answer.innovation_score,
                        'professional_skill_score': video_answer.professional_skill_score,
                        'stress_management_score': video_answer.stress_management_score
                    },
                    'ai_analysis': {
                        'ai_feedback': video_answer.ai_feedback,
                        'ai_score': video_answer.ai_score,
                        'ai_keywords': video_answer.ai_keywords,
                        'ai_sentiment': video_answer.ai_sentiment
                    }
                }
                
                # 4. 多模态分析结果 - 音频分析
                if hasattr(video_answer, 'audio_analysis'):
                    audio = video_answer.audio_analysis
                    question_detail['audio_analysis'] = {
                        'analysis_status': audio.analysis_status,
                        'transcribed_text': audio.transcribed_text,
                        'word_count': audio.word_count,
                        'speech_duration_seconds': audio.speech_duration_seconds,
                        'overall_audio_score': audio.overall_audio_score,
                        'speed_score': audio.speed_score,
                        'pitch_score': audio.pitch_score,
                        'volume_score': audio.volume_score,
                        'pause_score': audio.pause_score,
                        'fluency_score': audio.fluency_score,
                        'gender': audio.gender,
                        'speech_rate_syllables_per_second': audio.speech_rate_syllables_per_second,
                        'average_pitch_frequency_hz': audio.average_pitch_frequency_hz,
                        'average_volume_db': audio.average_volume_db,
                        'total_pause_frequency_per_second': audio.total_pause_frequency_per_second,
                        'articulation_rate_syllables_per_second': audio.articulation_rate_syllables_per_second,
                        'articulation_rate_score': audio.articulation_rate_score,
                        'correction_count_per_second': audio.correction_count_per_second,
                        'correction_count_score': audio.correction_count_score,
                        'f2_slope_hz_per_ms': audio.f2_slope_hz_per_ms,
                        'f2_slope_score': audio.f2_slope_score,
                        'created_at': audio.created_at.isoformat() if audio.created_at else None,
                        # 音频帧数据统计
                        'frame_data_count': audio.frame_data.count() if hasattr(audio, 'frame_data') else 0
                    }
                    
                    # 如果需要详细的音频帧数据（可选，数据量较大）
                    include_frame_data = getattr(request, 'query_params', {}).get('include_audio_frames', 'false').lower() == 'true'
                    if include_frame_data:
                        frame_data = []
                        for frame in audio.frame_data.all()[:100]:  # 限制最多100个数据点
                            frame_data.append({
                                'timestamp': frame.timestamp,
                                'pitch': frame.pitch,
                                'volume': frame.volume
                            })
                        question_detail['audio_analysis']['frame_data'] = frame_data
                else:
                    question_detail['audio_analysis'] = None
                
                # 5. 多模态分析结果 - 表情分析
                if hasattr(video_answer, 'expression_analysis'):
                    expression = video_answer.expression_analysis
                    question_detail['expression_analysis'] = {
                        'average_concentration': expression.average_concentration,
                        'emotion_avg_score': expression.emotion_avg_score,
                        'pose_avg_score': expression.pose_avg_score,
                        'gaze_avg_score': expression.gaze_avg_score,
                        'overall_evaluation': expression.overall_evaluation,
                        'total_frames': expression.total_frames,
                        'success_frames': expression.success_frames,
                        'analyzed_at': expression.analyzed_at.isoformat() if expression.analyzed_at else None,
                        # 表情帧数据统计
                        'frame_data_count': expression.frame_data.count() if hasattr(expression, 'frame_data') else 0
                    }
                    
                    # 如果需要详细的表情帧数据（可选，数据量较大）
                    include_frame_data = getattr(request, 'query_params', {}).get('include_expression_frames', 'false').lower() == 'true'
                    if include_frame_data:
                        frame_data = []
                        for frame in expression.frame_data.all()[:100]:  # 限制最多100个数据点
                            frame_data.append({
                                'timestamp': frame.timestamp,
                                'emotion_vector': frame.emotion_vector,
                                'head_angle_x': frame.head_angle_x,
                                'head_angle_y': frame.head_angle_y,
                                'head_angle_z': frame.head_angle_z,
                                'eye_angle_x': frame.eye_angle_x,
                                'eye_angle_y': frame.eye_angle_y
                            })
                        question_detail['expression_analysis']['frame_data'] = frame_data
                else:
                    question_detail['expression_analysis'] = None
                
                video_answers_detail.append(question_detail)
            
            report_data['video_answers_detail'] = video_answers_detail
            
            # 6. 汇总的多模态分析结果
            report_data['multimodal_analysis_summary'] = {
                'audio_analysis': report.audio_analysis_summary,
                'expression_analysis': report.expression_analysis_summary,
                'text_analysis': report.text_analysis_summary,
                'total_video_questions': len(video_answers_detail),
                'questions_with_audio_analysis': sum(1 for va in video_answers_detail if va['audio_analysis']),
                'questions_with_expression_analysis': sum(1 for va in video_answers_detail if va['expression_analysis']),
                'questions_with_ai_text_analysis': sum(1 for va in video_answers_detail if va['ai_analysis']['ai_feedback'])
            }
            
            # 7. 面试进度和时间信息
            report_data['interview_progress'] = {
                'session_id': session.id,
                'session_status': session.status,
                'started_at': session.started_at.isoformat() if session.started_at else None,
                'completed_at': session.completed_at.isoformat() if session.completed_at else None,
                'template_title': session.template.title,
                'template_description': session.template.description,
                'total_logical_questions': session.template.logist_questions.count(),
                'total_video_questions': session.template.video_questions.count(),
                'answered_video_questions': session.video_answers.count()
            }
            
            return Response({
                'success': True,
                'data': report_data
            }, status=status.HTTP_200_OK)
            
        except InterviewReport.DoesNotExist:
            return Response({
                'success': False,
                'error': '报告不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            logger.error(f"获取报告失败: {str(e)}")
            import traceback
            logger.error(f"详细错误信息: {traceback.format_exc()}")
            return Response({
                'success': False,
                'error': f'获取报告失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def post(self, request, report_id):
        """HR提交评论和决策"""
        try:
            report = InterviewReport.objects.get(id=report_id)
            
            # 更新HR评论
            hr_comments = request.data.get('hr_comments', '')
            hr_rating = request.data.get('hr_rating')
            hr_recommendation = request.data.get('hr_recommendation', '')
            final_decision = request.data.get('final_decision', '')
            decision_reason = request.data.get('decision_reason', '')
            
            if hr_comments:
                report.hr_comments = hr_comments
            
            if hr_rating and 1 <= hr_rating <= 5:
                report.hr_rating = hr_rating
            
            if hr_recommendation:
                report.hr_recommendation = hr_recommendation
            
            if final_decision:
                report.final_decision = final_decision
            
            if decision_reason:
                report.decision_reason = decision_reason
            
            report.hr_reviewed_at = timezone.now()
            report.save()
            
            return Response({
                'success': True,
                'message': 'HR评论提交成功',
                'data': {
                    'hr_comments': report.hr_comments,
                    'hr_rating': report.hr_rating,
                    'hr_recommendation': report.hr_recommendation,
                    'final_decision': report.final_decision,
                    'decision_reason': report.decision_reason,
                    'hr_reviewed_at': report.hr_reviewed_at.isoformat()
                }
            }, status=status.HTTP_200_OK)
            
        except InterviewReport.DoesNotExist:
            return Response({
                'success': False,
                'error': '报告不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'提交评论失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class BatchApprovalView(APIView):
    """批量审批接口"""
    permission_classes = [IsAuthenticated, IsHRUser]
    
    def post(self, request):
        """批量审批申请"""
        try:
            report_ids = request.data.get('report_ids', [])
            action = request.data.get('action', 'approve')  # approve/reject/follow_ai
            reason = request.data.get('reason', '')
            
            if not report_ids:
                return Response({
                    'success': False,
                    'error': '请选择要审批的报告'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            reports = InterviewReport.objects.filter(id__in=report_ids)
            updated_count = 0
            
            for report in reports:
                if action == 'approve':
                    report.final_decision = 'pass'
                    report.hr_recommendation = 'recommend'
                    report.decision_reason = reason or 'HR批量审批通过'
                elif action == 'reject':
                    report.final_decision = 'fail'
                    report.hr_recommendation = 'not_recommend'
                    report.decision_reason = reason or 'HR批量审批拒绝'
                elif action == 'follow_ai':
                    # 根据AI评分决定
                    if report.overall_score and report.overall_score >= 70:
                        report.final_decision = 'pass'
                        report.hr_recommendation = 'recommend'
                        report.decision_reason = f'跟随AI推荐，综合得分：{report.overall_score}'
                    else:
                        report.final_decision = 'fail'
                        report.hr_recommendation = 'not_recommend'
                        report.decision_reason = f'跟随AI推荐，综合得分：{report.overall_score}'
                
                report.hr_reviewed_at = timezone.now()
                report.save()
                updated_count += 1
            
            return Response({
                'success': True,
                'message': f'批量审批成功，处理了{updated_count}个报告',
                'data': {
                    'updated_count': updated_count,
                    'action': action
                }
            }, status=status.HTTP_200_OK)
            
        except Exception as e:
            return Response({
                'success': False,
                'error': f'批量审批失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class VoiceProfileViewSet(viewsets.ModelViewSet):
    """语音配置管理视图集"""
    queryset = VoiceProfile.objects.filter(is_active=True)
    serializer_class = VoiceProfileSerializer
    permission_classes = [IsAuthenticated, IsHRUser]
    
    def get_queryset(self):
        """HR可以查看所有语音配置，候选人只能查看启用的配置"""
        if self.request.user.is_hr:
            return VoiceProfile.objects.all()
        return VoiceProfile.objects.filter(is_active=True)


class SynthesizedAudioViewSet(viewsets.ModelViewSet):
    """合成音频管理视图集"""
    queryset = SynthesizedAudio.objects.all()
    serializer_class = SynthesizedAudioSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """根据用户角色过滤查询集"""
        if self.request.user.is_hr:
            return SynthesizedAudio.objects.all()
        # 候选人只能查看与自己的面试相关的音频
        return SynthesizedAudio.objects.filter(
            question__interview_templates__sessions__application__candidate=self.request.user
        ).distinct()


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_voice_profiles_for_interview(request, interview_id):
    """获取面试可用的语音配置列表"""
    try:
        interview_session = InterviewSession.objects.get(id=interview_id)
        
        # 检查权限
        if request.user.is_candidate:
            if interview_session.application.candidate != request.user:
                return Response({'error': '无权访问此面试'}, status=status.HTTP_403_FORBIDDEN)
        elif request.user.is_hr:
            if interview_session.application.job_posting.created_by != request.user:
                return Response({'error': '无权访问此面试'}, status=status.HTTP_403_FORBIDDEN)
        
        # 获取可用的语音配置
        voice_profiles = VoiceProfile.objects.filter(is_active=True)
        serializer = VoiceProfileSerializer(voice_profiles, many=True)
        
        return Response({
            'voice_profiles': serializer.data,
            'default_voice_profile': interview_session.template.default_voice_profile.id if interview_session.template.default_voice_profile else None
        })
        
    except InterviewSession.DoesNotExist:
        return Response({'error': '面试会话不存在'}, status=status.HTTP_404_NOT_FOUND)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def synthesize_audio_for_question(request, question_id, voice_profile_id):
    """为指定题目合成音频"""
    try:
        question = VideoQuestion.objects.get(id=question_id)
        voice_profile = VoiceProfile.objects.get(id=voice_profile_id, is_active=True)
        
        # 检查是否已经存在该题目的合成音频
        existing_audio = SynthesizedAudio.objects.filter(
            question=question,
            voice_profile=voice_profile
        ).first()
        
        if existing_audio and existing_audio.status == 'completed':
            serializer = SynthesizedAudioSerializer(existing_audio)
            return Response({
                'message': '音频已存在',
                'audio': serializer.data
            })
        
        # 如果存在但状态不是completed，删除重新创建
        if existing_audio:
            existing_audio.delete()
        
        # 创建新的合成音频记录
        synthesized_audio = SynthesizedAudio.objects.create(
            question=question,
            voice_profile=voice_profile,
            text_content=question.content,
            status='processing'
        )
        
        try:
            # 调用TTS API合成音频
            voice_config = voice_profile.get_voice_config()
            audio_path, file_size, duration = synthesize_text_to_audio(
                question.content, 
                voice_config
            )
            
            # 更新音频记录
            synthesized_audio.audio_file = audio_path
            synthesized_audio.file_size = file_size
            synthesized_audio.duration = duration
            synthesized_audio.status = 'completed'
            synthesized_audio.save()
            
            serializer = SynthesizedAudioSerializer(synthesized_audio)
            return Response({
                'message': '音频合成成功',
                'audio': serializer.data
            })
            
        except Exception as e:
            # 更新错误状态
            synthesized_audio.status = 'failed'
            synthesized_audio.error_message = str(e)
            synthesized_audio.save()
            
            return Response({
                'error': f'音频合成失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
    except VideoQuestion.DoesNotExist:
        return Response({'error': '题目不存在'}, status=status.HTTP_404_NOT_FOUND)
    except VoiceProfile.DoesNotExist:
        return Response({'error': '语音配置不存在'}, status=status.HTTP_404_NOT_FOUND)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def analyze_video_api(request):
    """同步视频分析API"""
    try:
        video_file = request.FILES.get('video')
        if not video_file:
            return Response({'error': '请上传视频文件'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 保存上传的视频文件
        video_path = os.path.join(settings.MEDIA_ROOT, 'temp_videos', video_file.name)
        os.makedirs(os.path.dirname(video_path), exist_ok=True)
        
        with open(video_path, 'wb+') as destination:
            for chunk in video_file.chunks():
                destination.write(chunk)
        
        # 获取分析参数
        interval_seconds = int(request.data.get('interval_seconds', 5))
        max_concurrency = int(request.data.get('max_concurrency', 3))
        
        # 执行视频分析
        service = VideoAnalysisService()
        result = service.sync_analyze_video(video_path, interval_seconds, max_concurrency)
        
        # 保存分析结果到数据库
        analysis = service.save_analysis_to_database(video_path, interval_seconds, result)
        
        return Response({
            'success': True,
            'analysis_id': analysis.id,
            'result': result
        })
        
    except Exception as e:
        return Response({
            'success': False,
            'error': str(e)
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def analyze_video_async_api(request):
    """异步视频分析API"""
    try:
        video_file = request.FILES.get('video')
        if not video_file:
            return Response({'error': '请上传视频文件'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 保存上传的视频文件
        video_path = os.path.join(settings.MEDIA_ROOT, 'temp_videos', video_file.name)
        os.makedirs(os.path.dirname(video_path), exist_ok=True)
        
        with open(video_path, 'wb+') as destination:
            for chunk in video_file.chunks():
                destination.write(chunk)
        
        # 获取分析参数
        interval_seconds = int(request.data.get('interval_seconds', 5))
        max_concurrency = int(request.data.get('max_concurrency', 3))
        
        # 创建初始分析记录
        service = VideoAnalysisService()
        analysis = ExpressionAnalysis.objects.create(
            video_path=video_path,
            interval_seconds=interval_seconds,
            total_frames=0,
            success_frames=0,
            analysis_status='processing'
        )
        
        # 在后台线程中执行分析
        def run_analysis():
            try:
                result = service.sync_analyze_video(video_path, interval_seconds, max_concurrency)
                service.save_analysis_to_database(video_path, interval_seconds, result)
                
                # 更新分析状态
                analysis.analysis_status = 'completed'
                analysis.save()
            except Exception as e:
                analysis.analysis_status = 'failed'
                analysis.error_message = str(e)
                analysis.save()
        
        thread = threading.Thread(target=run_analysis)
        thread.start()
        
        return Response({
            'success': True,
            'analysis_id': analysis.id,
            'message': '分析已开始，请稍后查询结果'
        })
        
    except Exception as e:
        return Response({
            'success': False,
            'error': str(e)
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_video_analysis_result(request, analysis_id):
    """获取视频分析结果"""
    try:
        analysis = ExpressionAnalysis.objects.get(id=analysis_id)
        
        # 获取帧分析数据
        frame_data = ExpressionFrameData.objects.filter(expression_analysis=analysis)
        frame_results = []
        
        for frame in frame_data:
            frame_result = {
                'frame_name': frame.frame_name,
                'frame_path': frame.frame_path,
                'concentration_score': frame.concentration_score,
                'analysis_status': frame.analysis_status,
                'primary_emotion': frame.primary_emotion,
                'emotion_confidence': frame.emotion_confidence,
                'emotion_score': frame.emotion_score,
                'emotion_evaluation': frame.emotion_evaluation,
                'yaw_angle': frame.yaw_angle,
                'pitch_angle': frame.pitch_angle,
                'roll_angle': frame.roll_angle,
                'pose_score': frame.pose_score,
                'pose_evaluation': frame.pose_evaluation,
                'left_gaze_angle': frame.left_gaze_angle,
                'right_gaze_angle': frame.right_gaze_angle,
                'avg_gaze_angle': frame.avg_gaze_angle,
                'gaze_score': frame.gaze_score,
                'gaze_evaluation': frame.gaze_evaluation,
            }
            
            # 获取情绪详细数据
            try:
                emotion_detail = frame.emotion_detail
                frame_result['emotion_data'] = {
                    'happiness': emotion_detail.happiness,
                    'surprise': emotion_detail.surprise,
                    'neutral': emotion_detail.neutral,
                    'sadness': emotion_detail.sadness,
                    'anger': emotion_detail.anger,
                    'disgust': emotion_detail.disgust,
                    'fear': emotion_detail.fear,
                }
            except:
                frame_result['emotion_data'] = {}
            
            frame_results.append(frame_result)
        
        result = {
            'analysis_id': analysis.id,
            'video_path': analysis.video_path,
            'analysis_time': analysis.analysis_time,
            'interval_seconds': analysis.interval_seconds,
            'total_frames': analysis.total_frames,
            'success_frames': analysis.success_frames,
            'average_concentration': analysis.average_concentration,
            'max_score': analysis.max_score,
            'min_score': analysis.min_score,
            'overall_evaluation': analysis.overall_evaluation,
            'emotion_avg_score': analysis.emotion_avg_score,
            'emotion_high_ratio': analysis.emotion_high_ratio,
            'pose_avg_score': analysis.pose_avg_score,
            'pose_high_ratio': analysis.pose_high_ratio,
            'gaze_avg_score': analysis.gaze_avg_score,
            'gaze_high_ratio': analysis.gaze_high_ratio,
            'frame_results': frame_results
        }
        
        return Response({
            'success': True,
            'result': result
        })
        
    except ExpressionAnalysis.DoesNotExist:
        return Response({
            'success': False,
            'error': '分析记录不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        return Response({
            'success': False,
            'error': str(e)
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def list_video_analyses(request):
    """获取视频分析列表"""
    try:
        analyses = ExpressionAnalysis.objects.all().order_by('-analysis_time')
        
        # 分页
        page = int(request.GET.get('page', 1))
        page_size = int(request.GET.get('page_size', 10))
        start = (page - 1) * page_size
        end = start + page_size
        
        analyses_page = analyses[start:end]
        
        result = []
        for analysis in analyses_page:
            result.append({
                'analysis_id': analysis.id,
                'video_path': analysis.video_path,
                'analysis_time': analysis.analysis_time,
                'total_frames': analysis.total_frames,
                'success_frames': analysis.success_frames,
                'average_concentration': analysis.average_concentration,
                'overall_evaluation': analysis.overall_evaluation,
            })
        
        return Response({
            'success': True,
            'data': result,
            'total': analyses.count(),
            'page': page,
            'page_size': page_size
        })
        
    except Exception as e:
        return Response({
            'success': False,
            'error': str(e)
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# 音频分析相关API接口
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_audio_analysis_detail(request, audio_analysis_id):
    """获取音频分析详情"""
    try:
        audio_analysis = AudioAnalysis.objects.get(id=audio_analysis_id)
        
        # 检查权限：只有HR或音频分析所属的候选人可以查看
        if not (request.user.is_hr or audio_analysis.video_answer.session.application.candidate == request.user):
            return Response({
                'success': False,
                'error': '无权限访问此音频分析'
            }, status=status.HTTP_403_FORBIDDEN)
        
        data = {
            'id': audio_analysis.id,
            'analysis_status': audio_analysis.analysis_status,
            'transcribed_text': audio_analysis.transcribed_text,
            'word_count': audio_analysis.word_count,
            'speech_duration_seconds': audio_analysis.speech_duration_seconds,
            'overall_audio_score': audio_analysis.overall_audio_score,
            'speed_score': audio_analysis.speed_score,
            'pitch_score': audio_analysis.pitch_score,
            'volume_score': audio_analysis.volume_score,
            'pause_score': audio_analysis.pause_score,
            'fluency_score': audio_analysis.fluency_score,
            'gender': audio_analysis.gender,
            'speech_rate_syllables_per_second': audio_analysis.speech_rate_syllables_per_second,
            'average_pitch_frequency_hz': audio_analysis.average_pitch_frequency_hz,
            'average_volume_db': audio_analysis.average_volume_db,
            'total_pause_frequency_per_second': audio_analysis.total_pause_frequency_per_second,
            'articulation_rate_syllables_per_second': audio_analysis.articulation_rate_syllables_per_second,
            'articulation_rate_score': audio_analysis.articulation_rate_score,
            'correction_count_per_second': audio_analysis.correction_count_per_second,
            'correction_count_score': audio_analysis.correction_count_score,
            'f2_slope_hz_per_ms': audio_analysis.f2_slope_hz_per_ms,
            'f2_slope_score': audio_analysis.f2_slope_score,
            'created_at': audio_analysis.created_at.isoformat() if audio_analysis.created_at else None,
            'updated_at': audio_analysis.updated_at.isoformat() if audio_analysis.updated_at else None,
        }
        
        # 如果需要帧数据
        include_frame_data = request.query_params.get('include_frame_data', 'false').lower() == 'true'
        if include_frame_data:
            frame_data = []
            for frame in audio_analysis.frame_data.all()[:100]:  # 限制最多100个数据点
                frame_data.append({
                    'timestamp': frame.timestamp,
                    'pitch': frame.pitch,
                    'volume': frame.volume,
                    'pitch_score_per_second': frame.pitch_score_per_second,
                    'volume_score_per_second': frame.volume_score_per_second,
                })
            data['frame_data'] = frame_data
        
        return Response({
            'success': True,
            'data': data
        }, status=status.HTTP_200_OK)
        
    except AudioAnalysis.DoesNotExist:
        return Response({
            'success': False,
            'error': '音频分析记录不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        return Response({
            'success': False,
            'error': f'获取音频分析详情失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_video_answer_audio_analysis(request, video_answer_id):
    """获取视频答案的音频分析"""
    try:
        video_answer = VideoAnswer.objects.get(id=video_answer_id)
        
        # 检查权限
        if not (request.user.is_hr or video_answer.session.application.candidate == request.user):
            return Response({
                'success': False,
                'error': '无权限访问此视频答案'
            }, status=status.HTTP_403_FORBIDDEN)
        
        if not hasattr(video_answer, 'audio_analysis') or not video_answer.audio_analysis:
            return Response({
                'success': False,
                'error': '该视频答案暂无音频分析'
            }, status=status.HTTP_404_NOT_FOUND)
        
        audio_analysis = video_answer.audio_analysis
        
        data = {
            'id': audio_analysis.id,
            'analysis_status': audio_analysis.analysis_status,
            'transcribed_text': audio_analysis.transcribed_text,
            'word_count': audio_analysis.word_count,
            'speech_duration_seconds': audio_analysis.speech_duration_seconds,
            'overall_audio_score': audio_analysis.overall_audio_score,
            'speed_score': audio_analysis.speed_score,
            'pitch_score': audio_analysis.pitch_score,
            'volume_score': audio_analysis.volume_score,
            'pause_score': audio_analysis.pause_score,
            'fluency_score': audio_analysis.fluency_score,
            'gender': audio_analysis.gender,
            'speech_rate_syllables_per_second': audio_analysis.speech_rate_syllables_per_second,
            'average_pitch_frequency_hz': audio_analysis.average_pitch_frequency_hz,
            'average_volume_db': audio_analysis.average_volume_db,
            'total_pause_frequency_per_second': audio_analysis.total_pause_frequency_per_second,
            'articulation_rate_syllables_per_second': audio_analysis.articulation_rate_syllables_per_second,
            'articulation_rate_score': audio_analysis.articulation_rate_score,
            'correction_count_per_second': audio_analysis.correction_count_per_second,
            'correction_count_score': audio_analysis.correction_count_score,
            'f2_slope_hz_per_ms': audio_analysis.f2_slope_hz_per_ms,
            'f2_slope_score': audio_analysis.f2_slope_score,
            'created_at': audio_analysis.created_at.isoformat() if audio_analysis.created_at else None,
        }
        
        return Response({
            'success': True,
            'data': data
        }, status=status.HTTP_200_OK)
        
    except VideoAnswer.DoesNotExist:
        return Response({
            'success': False,
            'error': '视频答案不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        return Response({
            'success': False,
            'error': f'获取音频分析失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_interview_audio_summary(request, application_id):
    """获取面试的音频分析汇总"""
    try:
        application = JobApplication.objects.get(id=application_id)
        
        # 检查权限
        if not (request.user.is_hr or application.candidate == request.user):
            return Response({
                'success': False,
                'error': '无权限访问此申请'
            }, status=status.HTTP_403_FORBIDDEN)
        
        if not hasattr(application, 'interview_session'):
            return Response({
                'success': False,
                'error': '该申请暂无面试会话'
            }, status=status.HTTP_404_NOT_FOUND)
        
        session = application.interview_session
        video_answers = session.video_answers.all()
        
        audio_summary = {
            'total_video_answers': video_answers.count(),
            'answers_with_audio_analysis': 0,
            'average_overall_audio_score': 0,
            'average_speed_score': 0,
            'average_pitch_score': 0,
            'average_volume_score': 0,
            'average_pause_score': 0,
            'average_fluency_score': 0,
            'total_speech_duration': 0,
            'total_word_count': 0,
            'audio_analysis_details': []
        }
        
        total_scores = {
            'overall_audio_score': 0,
            'speed_score': 0,
            'pitch_score': 0,
            'volume_score': 0,
            'pause_score': 0,
            'fluency_score': 0
        }
        
        for video_answer in video_answers:
            if hasattr(video_answer, 'audio_analysis') and video_answer.audio_analysis:
                audio_analysis = video_answer.audio_analysis
                audio_summary['answers_with_audio_analysis'] += 1
                
                # 累加各项得分
                for score_field in total_scores:
                    score_value = getattr(audio_analysis, score_field, 0) or 0
                    total_scores[score_field] += score_value
                
                # 累加时长和字数
                audio_summary['total_speech_duration'] += audio_analysis.speech_duration_seconds or 0
                audio_summary['total_word_count'] += audio_analysis.word_count or 0
                
                # 添加详细信息
                audio_summary['audio_analysis_details'].append({
                    'video_answer_id': video_answer.id,
                    'question_title': video_answer.question.title,
                    'analysis_status': audio_analysis.analysis_status,
                    'overall_audio_score': audio_analysis.overall_audio_score,
                    'speed_score': audio_analysis.speed_score,
                    'pitch_score': audio_analysis.pitch_score,
                    'volume_score': audio_analysis.volume_score,
                    'pause_score': audio_analysis.pause_score,
                    'fluency_score': audio_analysis.fluency_score,
                    'speech_duration_seconds': audio_analysis.speech_duration_seconds,
                    'word_count': audio_analysis.word_count,
                    'created_at': audio_analysis.created_at.isoformat() if audio_analysis.created_at else None,
                })
        
        # 计算平均分
        if audio_summary['answers_with_audio_analysis'] > 0:
            for score_field in total_scores:
                avg_field = f'average_{score_field}'
                audio_summary[avg_field] = round(total_scores[score_field] / audio_summary['answers_with_audio_analysis'], 2)
        
        return Response({
            'success': True,
            'data': audio_summary
        }, status=status.HTTP_200_OK)
        
    except JobApplication.DoesNotExist:
        return Response({
            'success': False,
            'error': '申请不存在'
        }, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        return Response({
            'success': False,
            'error': f'获取音频分析汇总失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def list_audio_analyses(request):
    """获取音频分析列表（HR功能）"""
    try:
        if not request.user.is_hr:
            return Response({
                'success': False,
                'error': '只有HR可以查看音频分析列表'
            }, status=status.HTTP_403_FORBIDDEN)
        
        # 获取查询参数
        page = int(request.query_params.get('page', 1))
        page_size = int(request.query_params.get('page_size', 10))
        status_filter = request.query_params.get('status', None)
        application_id = request.query_params.get('application_id', None)
        
        queryset = AudioAnalysis.objects.select_related(
            'video_answer__session__application__candidate',
            'video_answer__question'
        ).all()
        
        # 应用筛选条件
        if status_filter:
            queryset = queryset.filter(analysis_status=status_filter)
        
        if application_id:
            queryset = queryset.filter(video_answer__session__application_id=application_id)
        
        # 分页
        total_count = queryset.count()
        start = (page - 1) * page_size
        end = start + page_size
        audio_analyses = queryset[start:end]
        
        data = []
        for audio_analysis in audio_analyses:
            data.append({
                'id': audio_analysis.id,
                'video_answer_id': audio_analysis.video_answer.id,
                'question_title': audio_analysis.video_answer.question.title,
                'candidate_name': audio_analysis.video_answer.session.application.candidate.name,
                'application_id': audio_analysis.video_answer.session.application.id,
                'analysis_status': audio_analysis.analysis_status,
                'overall_audio_score': audio_analysis.overall_audio_score,
                'word_count': audio_analysis.word_count,
                'speech_duration_seconds': audio_analysis.speech_duration_seconds,
                'created_at': audio_analysis.created_at.isoformat() if audio_analysis.created_at else None,
            })
        
        return Response({
            'success': True,
            'data': {
                'audio_analyses': data,
                'pagination': {
                    'page': page,
                    'page_size': page_size,
                    'total_count': total_count,
                    'total_pages': (total_count + page_size - 1) // page_size
                }
            }
        }, status=status.HTTP_200_OK)
        
    except Exception as e:
        return Response({
            'success': False,
            'error': f'获取音频分析列表失败: {str(e)}'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class ResumeMatchView(APIView):
    """简历匹配API视图"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        """
        上传简历文件进行匹配分析
        
        请求参数:
        - resume_file: 简历文件 (PDF, DOCX, TXT等)
        - job_posting_id: 职位ID (可选，如果不提供则使用默认职位描述)
        - threshold_score: 通过阈值 (可选，默认70.0)
        """
        try:
            # 获取上传的简历文件
            resume_file = request.FILES.get('resume_file')
            if not resume_file:
                return Response({
                    'success': False,
                    'error': '请上传简历文件'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取职位信息
            job_posting_id = request.data.get('job_posting_id')
            if job_posting_id:
                try:
                    job_posting = JobPosting.objects.get(id=job_posting_id)
                except JobPosting.DoesNotExist:
                    return Response({
                        'success': False,
                        'error': '指定的职位不存在'
                    }, status=status.HTTP_404_NOT_FOUND)
            else:
                # 如果没有指定职位，使用默认职位描述
                # 这里可以创建一个默认的职位描述或返回错误
                return Response({
                    'success': False,
                    'error': '请指定职位ID'
                }, status=status.HTTP_400_BAD_REQUEST)
            
            # 获取阈值
            threshold_score = float(request.data.get('threshold_score', 70.0))
            
            # 保存上传的文件
            import os
            from django.conf import settings
            
            # 创建临时文件路径
            temp_dir = os.path.join(settings.MEDIA_ROOT, 'temp_resumes')
            os.makedirs(temp_dir, exist_ok=True)
            
            file_path = os.path.join(temp_dir, resume_file.name)
            with open(file_path, 'wb+') as destination:
                for chunk in resume_file.chunks():
                    destination.write(chunk)
            
            try:
                # 调用简历匹配模块
                from .resume_matcher.main import process_resume_from_job_posting
                result = process_resume_from_job_posting(file_path, job_posting)
                
                # 清理临时文件
                if os.path.exists(file_path):
                    os.unlink(file_path)
                
                # 检查是否有错误
                if "error" in result:
                    return Response({
                        'success': False,
                        'error': f'简历匹配失败: {result["error"]}'
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                
                # 返回匹配结果
                return Response({
                    'success': True,
                    'data': result
                }, status=status.HTTP_200_OK)
                
            except Exception as e:
                # 清理临时文件
                if os.path.exists(file_path):
                    os.unlink(file_path)
                raise e
                
        except Exception as e:
            return Response({
                'success': False,
                'error': f'简历匹配过程中发生错误: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
